fix: edit gpu_selector failed

This commit is contained in:
jialin
2025-09-17 19:53:40 +08:00
parent 4d9dec8511
commit bf400547e1
17 changed files with 296 additions and 544 deletions
+1
View File
@@ -78,6 +78,7 @@ export default {
colorText: 'rgba(0,0,0,1)', colorText: 'rgba(0,0,0,1)',
colorPrimary: '#007BFF', colorPrimary: '#007BFF',
colorSuccess: '#54cc98', colorSuccess: '#54cc98',
colorBorder: '#d3d0d9',
borderRadius: 4, borderRadius: 4,
borderRadiusSM: 2, borderRadiusSM: 2,
colorBgContainer: '#fff', colorBgContainer: '#fff',
+15 -56
View File
@@ -8,8 +8,8 @@ import _ from 'lodash';
import React, { forwardRef, useImperativeHandle } from 'react'; import React, { forwardRef, useImperativeHandle } from 'react';
import { excludeFields, ScheduleValueMap, sourceOptions } from '../config'; import { excludeFields, ScheduleValueMap, sourceOptions } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { FormInnerContext } from '../config/form-context'; import { FormContext } from '../config/form-context';
import { FormData, SourceType } from '../config/types'; import { DeployFormKey, FormData, SourceType } from '../config/types';
import CatalogFrom from '../forms/catalog'; import CatalogFrom from '../forms/catalog';
import HuggingFaceForm from '../forms/hugging-face'; import HuggingFaceForm from '../forms/hugging-face';
import LocalPathForm from '../forms/local-path'; import LocalPathForm from '../forms/local-path';
@@ -21,8 +21,8 @@ interface DataFormProps {
ref?: any; ref?: any;
source: SourceType; source: SourceType;
action: PageActionType; action: PageActionType;
selectedModel: any;
isGGUF: boolean; isGGUF: boolean;
formKey: DeployFormKey;
sourceDisable?: boolean; sourceDisable?: boolean;
backendOptions?: Global.BaseOption<string>[]; backendOptions?: Global.BaseOption<string>[];
sourceList?: Global.BaseOption<string>[]; sourceList?: Global.BaseOption<string>[];
@@ -38,6 +38,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
const { const {
action, action,
isGGUF, isGGUF,
formKey,
initialValues, initialValues,
sourceDisable = true, sourceDisable = true,
backendOptions, backendOptions,
@@ -77,7 +78,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
}); });
} }
form.setFieldsValue({ form.setFieldsValue({
...updates, backend_version: '',
backend_parameters: [], backend_parameters: [],
env: null env: null
}); });
@@ -116,11 +117,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
// generate the data is available for the backend including the gpu_ids // generate the data is available for the backend including the gpu_ids
const handleOk = async (formdata: FormData) => { const handleOk = async (formdata: FormData) => {
let data = _.cloneDeep(formdata); let data = _.cloneDeep(formdata);
data.categories = Array.isArray(data.categories) data.categories = data.categories ? [data.categories] : [];
? data.categories
: data.categories
? [data.categories]
: [];
const gpuSelector = generateGPUIds(data); const gpuSelector = generateGPUIds(data);
const allValues = { const allValues = {
..._.omit(data, ['scheduleType']), ..._.omit(data, ['scheduleType']),
@@ -166,18 +163,21 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
getFieldsValue: () => { getFieldsValue: () => {
return form.getFieldsValue(); return form.getFieldsValue();
}, },
getGPUOptionList(params: { clusterId: number }) { getGPUOptionList: async (params: { clusterId: number }) => {
getGPUOptionList(params); return await getGPUOptionList(params);
} }
}; };
}); });
return ( return (
<FormInnerContext.Provider <FormContext.Provider
value={{ value={{
onBackendChange: handleBackendChange, isGGUF: isGGUF,
formKey: formKey,
pageAction: action,
gpuOptions: gpuOptions,
onValuesChange: onValuesChange, onValuesChange: onValuesChange,
gpuOptions: gpuOptions onBackendChange: handleBackendChange
}} }}
> >
<Form <Form
@@ -261,47 +261,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
></SealSelect> ></SealSelect>
} }
</Form.Item> </Form.Item>
{/* <Form.Item name="backend" rules={[{ required: true }]}>
<SealSelect
required
onChange={handleBackendChange}
label={intl.formatMessage({ id: 'models.form.backend' })}
description={<TooltipList list={backendTipsList}></TooltipList>}
options={
backendOptions ?? [
{
label: backendLabelMap[backendOptionsMap.vllm],
value: backendOptionsMap.vllm,
disabled:
props.source === modelSourceMap.local_path_value
? false
: isGGUF
},
{
label: backendLabelMap[backendOptionsMap.ascendMindie],
value: backendOptionsMap.ascendMindie,
disabled:
props.source === modelSourceMap.local_path_value
? false
: isGGUF
},
{
label: backendLabelMap[backendOptionsMap.voxBox],
value: backendOptionsMap.voxBox,
disabled:
props.source === modelSourceMap.local_path_value
? false
: props.source === modelSourceMap.ollama_library_value ||
isGGUF
}
]
}
disabled={
action === PageAction.EDIT &&
props.source !== modelSourceMap.local_path_value
}
></SealSelect>
</Form.Item> */}
<CatalogFrom></CatalogFrom> <CatalogFrom></CatalogFrom>
<Form.Item<FormData> name="description"> <Form.Item<FormData> name="description">
<SealInput.TextArea <SealInput.TextArea
@@ -321,7 +280,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
handleBackendChange={handleBackendChange} handleBackendChange={handleBackendChange}
></AdvanceConfig> ></AdvanceConfig>
</Form> </Form>
</FormInnerContext.Provider> </FormContext.Provider>
); );
}); });
@@ -11,11 +11,12 @@ import styled from 'styled-components';
import { queryCatalogItemSpec } from '../apis'; import { queryCatalogItemSpec } from '../apis';
import { import {
defaultFormValues, defaultFormValues,
deployFormKeyMap,
modelCategoriesMap, modelCategoriesMap,
sourceOptions sourceOptions
} from '../config'; } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { FormContext } from '../config/form-context'; import { CatalogFormContext } from '../config/form-context';
import { CatalogSpec, FormData, ListItem, SourceType } from '../config/types'; import { CatalogSpec, FormData, ListItem, SourceType } from '../config/types';
import { useCheckCompatibility } from '../hooks'; import { useCheckCompatibility } from '../hooks';
import useFormInitialValues from '../hooks/use-form-initial-values'; import useFormInitialValues from '../hooks/use-form-initial-values';
@@ -107,8 +108,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const [isGGUF, setIsGGUF] = useState<boolean>(false); const [isGGUF, setIsGGUF] = useState<boolean>(false);
const [sourceList, setSourceList] = useState<any[]>([]); const [sourceList, setSourceList] = useState<any[]>([]);
const [backendList, setBackendList] = useState<any[]>([]); const [backendList, setBackendList] = useState<any[]>([]);
const [sizeOptions, setSizeOptions] = useState<any[]>([]); const [sizeOptions, setSizeOptions] = useState<Global.BaseOption<number>[]>(
const [quantizationOptions, setQuantizationOptions] = useState<any[]>([]); []
);
const [quantizationOptions, setQuantizationOptions] = useState<
Global.BaseOption<string>[]
>([]);
const sourceGroupMap = useRef<any>({}); const sourceGroupMap = useRef<any>({});
const axiosToken = useRef<any>(null); const axiosToken = useRef<any>(null);
const selectSpecRef = useRef<CatalogSpec>({} as CatalogSpec); const selectSpecRef = useRef<CatalogSpec>({} as CatalogSpec);
@@ -529,16 +534,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
width={width} width={width}
footer={false} footer={false}
> >
<FormContext.Provider <CatalogFormContext.Provider
value={{ value={{
isGGUF: isGGUF,
byBuiltIn: true,
sizeOptions: sizeOptions, sizeOptions: sizeOptions,
quantizationOptions: quantizationOptions, quantizationOptions: quantizationOptions,
pageAction: action,
onSizeChange: handleOnSizeChange, onSizeChange: handleOnSizeChange,
onQuantizationChange: handleOnQuantizationChange, onQuantizationChange: handleOnQuantizationChange
onValuesChange: onValuesChange
}} }}
> >
<FormWrapper> <FormWrapper>
@@ -590,10 +591,10 @@ const AddModal: React.FC<AddModalProps> = (props) => {
fields={[]} fields={[]}
source={source} source={source}
action={action} action={action}
selectedModel={{}}
onOk={handleOk} onOk={handleOk}
ref={form} ref={form}
isGGUF={isGGUF} isGGUF={isGGUF}
formKey={deployFormKeyMap.catalog}
sourceDisable={false} sourceDisable={false}
backendOptions={backendList} backendOptions={backendList}
sourceList={sourceList} sourceList={sourceList}
@@ -605,7 +606,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
</> </>
</ColumnWrapper> </ColumnWrapper>
</FormWrapper> </FormWrapper>
</FormContext.Provider> </CatalogFormContext.Provider>
</GSDrawer> </GSDrawer>
); );
}; };
+61 -86
View File
@@ -1,20 +1,14 @@
import ModalFooter from '@/components/modal-footer'; import ModalFooter from '@/components/modal-footer';
import GSDrawer from '@/components/scroller-modal/gs-drawer'; import GSDrawer from '@/components/scroller-modal/gs-drawer';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import useDeferredRequest from '@/hooks/use-deferred-request';
import { ProviderValueMap } from '@/pages/cluster-management/config'; import { ProviderValueMap } from '@/pages/cluster-management/config';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button } from 'antd'; import { Button } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { import { defaultFormValues, deployFormKeyMap, modelSourceMap } from '../config';
defaultFormValues,
getSourceRepoConfigValue,
modelSourceMap
} from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { FormContext } from '../config/form-context';
import { FormData, SourceType } from '../config/types'; import { FormData, SourceType } from '../config/types';
import { import {
MessageStatus, MessageStatus,
@@ -32,16 +26,10 @@ import SearchModel from './search-model';
import Separator from './separator'; import Separator from './separator';
import TitleWrapper from './title-wrapper'; import TitleWrapper from './title-wrapper';
const resetFieldsByModel = ['backend_version', 'backend_parameters', 'env'];
const pickFieldsFromSpec = ['backend_version', 'backend_parameters', 'env']; const pickFieldsFromSpec = ['backend_version', 'backend_parameters', 'env'];
const dropFieldsFromForm = ['name', 'file_name', 'repo_id', 'backend']; const dropFieldsFromForm = ['name', 'file_name', 'repo_id', 'backend'];
const resetFields = ['worker_selector', 'env']; const resetFields = ['worker_selector', 'env'];
const resetFieldsByFile = [
'cpu_offloading',
'distributed_inference_across_workers'
];
const ModalFooterStyle = { const ModalFooterStyle = {
padding: '16px 24px', padding: '16px 24px',
display: 'flex', display: 'flex',
@@ -133,11 +121,6 @@ const AddModal: FC<AddModalProps> = (props) => {
const requestModelIdRef = useRef<number>(0); const requestModelIdRef = useRef<number>(0);
const currentSelectedModel = useRef<any>({}); const currentSelectedModel = useRef<any>({});
const { run: fetchModelFiles } = useDeferredRequest(
() => modelFileRef.current?.fetchModelFiles?.(),
100
);
const updateSelectedModel = (model: any) => { const updateSelectedModel = (model: any) => {
currentSelectedModel.current = model; currentSelectedModel.current = model;
setSelectedModel(model); setSelectedModel(model);
@@ -310,8 +293,8 @@ const AddModal: FC<AddModalProps> = (props) => {
}; };
const handleOnOk = async (allValues: FormData) => { const handleOnOk = async (allValues: FormData) => {
const result = getSourceRepoConfigValue(props.source, allValues).values; console.log('handleOnOk:', allValues);
onOk(result); onOk(allValues);
}; };
const handleSubmitAnyway = async () => { const handleSubmitAnyway = async () => {
@@ -503,74 +486,66 @@ const AddModal: FC<AddModalProps> = (props) => {
</> </>
)} )}
<FormContext.Provider <FormWrapper>
value={{ <ColumnWrapper
isGGUF: isGGUF, paddingBottom={warningStatus.show ? 170 : 50}
pageAction: action, footer={
onValuesChange: onValuesChange
}}
>
<FormWrapper>
<ColumnWrapper
paddingBottom={warningStatus.show ? 170 : 50}
footer={
<>
<CompatibilityAlert
showClose={true}
onClose={() => {
setWarningStatus({
show: false,
message: ''
});
}}
warningStatus={warningStatus}
contentStyle={{ paddingInline: 0 }}
></CompatibilityAlert>
<ModalFooter
onCancel={handleCancel}
onOk={handleSumit}
showOkBtn={!showExtraButton}
extra={
showExtraButton && (
<Button
type="primary"
onClick={handleSubmitAnyway}
disabled={isGGUF}
>
{intl.formatMessage({
id: 'models.form.submit.anyway'
})}
</Button>
)
}
style={ModalFooterStyle}
></ModalFooter>
</>
}
>
<> <>
{SEARCH_SOURCE.includes(source) && <CompatibilityAlert
deploymentType === 'modelList' && ( showClose={true}
<TitleWrapper> onClose={() => {
{intl.formatMessage({ id: 'models.form.configurations' })} setWarningStatus({
</TitleWrapper> show: false,
)} message: ''
<DataForm });
initialValues={initialValues} }}
source={source} warningStatus={warningStatus}
action={action} contentStyle={{ paddingInline: 0 }}
clusterList={clusterList} ></CompatibilityAlert>
selectedModel={selectedModel} <ModalFooter
onOk={handleOnOk} onCancel={handleCancel}
ref={form} onOk={handleSumit}
isGGUF={isGGUF} showOkBtn={!showExtraButton}
onBackendChange={handleBackendChange} extra={
onValuesChange={onValuesChange} showExtraButton && (
></DataForm> <Button
type="primary"
onClick={handleSubmitAnyway}
disabled={isGGUF}
>
{intl.formatMessage({
id: 'models.form.submit.anyway'
})}
</Button>
)
}
style={ModalFooterStyle}
></ModalFooter>
</> </>
</ColumnWrapper> }
</FormWrapper> >
</FormContext.Provider> <>
{SEARCH_SOURCE.includes(source) &&
deploymentType === 'modelList' && (
<TitleWrapper>
{intl.formatMessage({ id: 'models.form.configurations' })}
</TitleWrapper>
)}
<DataForm
formKey={deployFormKeyMap.deployment}
initialValues={initialValues}
source={source}
action={action}
clusterList={clusterList}
onOk={handleOnOk}
ref={form}
isGGUF={isGGUF}
onBackendChange={handleBackendChange}
onValuesChange={onValuesChange}
></DataForm>
</>
</ColumnWrapper>
</FormWrapper>
</div> </div>
</GSDrawer> </GSDrawer>
); );
+4 -25
View File
@@ -7,7 +7,7 @@ import { Form } from 'antd';
import React from 'react'; import React from 'react';
import { scheduleList, ScheduleValueMap } from '../config'; import { scheduleList, ScheduleValueMap } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { useFormContext, useFormInnerContext } from '../config/form-context'; import { useCatalogFormContext, useFormContext } from '../config/form-context';
import GPUCard from './gpu-card'; import GPUCard from './gpu-card';
const scheduleTypeTips = [ const scheduleTypeTips = [
@@ -29,8 +29,8 @@ const scheduleTypeTips = [
const Performance: React.FC = () => { const Performance: React.FC = () => {
const intl = useIntl(); const intl = useIntl();
const { gpuOptions } = useFormInnerContext(); const { onValuesChange, gpuOptions } = useFormContext();
const { onValuesChange, onQuantizationChange } = useFormContext(); const { onQuantizationChange } = useCatalogFormContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const form = Form.useFormInstance(); const form = Form.useFormInstance();
@@ -62,28 +62,7 @@ const Performance: React.FC = () => {
<Form.Item name={['gpu_selector', 'gpu_type']}> <Form.Item name={['gpu_selector', 'gpu_type']}>
<SealSelect <SealSelect
label={intl.formatMessage({ id: 'models.form.gpuType' })} label={intl.formatMessage({ id: 'models.form.gpuType' })}
options={[ options={[]}
{
label: 'NVIDIA 4090',
value: 'nvidia-4090'
},
{
label: 'NVIDIA A100',
value: 'nvidia-a100'
},
{
label: 'NVIDIA H100',
value: 'nvidia-h100'
},
{
label: 'Huawei 910B',
value: 'huawei-910b'
},
{
label: 'Huawei 910C',
value: 'huawei-910c'
}
]}
></SealSelect> ></SealSelect>
</Form.Item> </Form.Item>
<Form.Item name={['gpu_selector', 'gpu_count']}> <Form.Item name={['gpu_selector', 'gpu_count']}>
+2 -47
View File
@@ -1,11 +1,10 @@
import { getRequestId, setRquestId } from '@/atoms/models'; import { getRequestId, setRquestId } from '@/atoms/models';
import BaseSelect from '@/components/seal-form/base/select'; import BaseSelect from '@/components/seal-form/base/select';
import { createAxiosToken } from '@/hooks/use-chunk-request'; import { createAxiosToken } from '@/hooks/use-chunk-request';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Pagination, Tooltip } from 'antd'; import { Pagination } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {
evaluationsModelSpec, evaluationsModelSpec,
@@ -62,7 +61,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
const { const {
modelSource, modelSource,
isDownload, isDownload,
hasLinuxWorker,
gpuOptions, gpuOptions,
clusterId, clusterId,
setLoadingModel, setLoadingModel,
@@ -94,7 +92,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
const axiosTokenRef = useRef<any>(null); const axiosTokenRef = useRef<any>(null);
const checkTokenRef = useRef<any>(null); const checkTokenRef = useRef<any>(null);
const searchInputRef = useRef<any>(''); const searchInputRef = useRef<any>('');
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 requestIdRef = useRef<number>(0); const requestIdRef = useRef<number>(0);
@@ -458,15 +455,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
}); });
}; };
const handleFilterGGUFChange = (e: any) => {
filterGGUFRef.current = e.target.checked;
handleOnSearchRepo({
sortType: dataSource.sortType,
page: 1,
perPage: query.perPage
});
};
const handleOnPageChange = (page: number) => { const handleOnPageChange = (page: number) => {
if (modelSource === modelSourceMap.huggingface_value) { if (modelSource === modelSourceMap.huggingface_value) {
const currentList = getCurrentPage(page); const currentList = getCurrentPage(page);
@@ -507,32 +495,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
handleOnSelectModel(model, true); handleOnSelectModel(model, true);
}; };
const renderGGUFTips = useMemo(() => {
return (
<Tooltip
styles={{
body: {
width: 'max-content'
}
}}
title={
<UL>
<li>{intl.formatMessage({ id: 'models.search.gguf.tips' })}</li>
<li>{intl.formatMessage({ id: 'models.search.vllm.tips' })}</li>
<li>
{intl.formatMessage({
id: 'models.search.voxbox.tips'
})}
</li>
</UL>
}
>
GGUF
<QuestionCircleOutlined className="m-l-4" />
</Tooltip>
);
}, [intl]);
const renderHFSearch = () => { const renderHFSearch = () => {
return ( return (
<> <>
@@ -562,13 +524,6 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
size="middle" size="middle"
style={{ width: '150px' }} style={{ width: '150px' }}
></BaseSelect> ></BaseSelect>
{/* <Checkbox
onChange={handleFilterGGUFChange}
className="m-l-8"
checked={filterGGUFRef.current}
>
{renderGGUFTips}
</Checkbox> */}
</span> </span>
<PaginationMain <PaginationMain
simple={{ readOnly: true }} simple={{ readOnly: true }}
+2 -4
View File
@@ -123,7 +123,7 @@ const Models: React.FC<ModelsProps> = ({
loadend, loadend,
total total
}) => { }) => {
const { getGPUOptionList, generateFormValues, clusterList, getClusterList } = const { generateFormValues, clusterList, getClusterList } =
useFormInitialValues(); useFormInitialValues();
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll(); const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
const [updateFormInitials, setUpdateFormInitials] = useState<{ const [updateFormInitials, setUpdateFormInitials] = useState<{
@@ -188,9 +188,7 @@ const Models: React.FC<ModelsProps> = ({
useEffect(() => { useEffect(() => {
const getData = async () => { const getData = async () => {
const res = await getClusterList(); await getClusterList();
const clusterId = res[0]?.value;
await getGPUOptionList({ clusterId });
}; };
getData(); getData();
return () => { return () => {
+46 -160
View File
@@ -1,38 +1,29 @@
import ModalFooter from '@/components/modal-footer'; import ModalFooter from '@/components/modal-footer';
import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Form, Modal } from 'antd'; import { Button, Modal } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useEffect, useMemo, useRef } from 'react'; import React, { useEffect, useMemo, useRef } from 'react';
import { import {
updateExcludeFields as excludeFields, deployFormKeyMap,
getSourceRepoConfigValue,
modelSourceMap, modelSourceMap,
ScheduleValueMap, ScheduleValueMap,
sourceOptions,
updateIgnoreFields updateIgnoreFields
} from '../config'; } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { FormContext, FormInnerContext } from '../config/form-context'; import { FormData } from '../config/types';
import { FormData, ListItem } from '../config/types'; import { generateGPUSelector } from '../config/utils';
import HuggingFaceForm from '../forms/hugging-face';
import LocalPathForm from '../forms/local-path';
import { useCheckCompatibility } from '../hooks'; import { useCheckCompatibility } from '../hooks';
import { useGenerateGPUOptions } from '../hooks/use-form-initial-values';
import AdvanceConfig from './advance-config';
import ColumnWrapper from './column-wrapper'; import ColumnWrapper from './column-wrapper';
import CompatibilityAlert from './compatible-alert'; import CompatibilityAlert from './compatible-alert';
import DataForm from './data-form';
type AddModalProps = { type AddModalProps = {
title: string; title: string;
action: PageActionType; action: PageActionType;
open: boolean; open: boolean;
updateFormInitials: { updateFormInitials: {
data?: ListItem; data: FormData;
isGGUF: boolean; isGGUF: boolean;
}; };
clusterList: Global.BaseOption< clusterList: Global.BaseOption<
@@ -56,22 +47,15 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const { const {
setWarningStatus, setWarningStatus,
generateGPUIds,
handleBackendChangeBefore, handleBackendChangeBefore,
checkTokenRef, checkTokenRef,
warningStatus warningStatus
} = useCheckCompatibility(); } = useCheckCompatibility();
const { getGPUOptionList, gpuOptions } = useGenerateGPUOptions();
const { getRuleMessage } = useAppUtils(); const formRef = useRef<any>(null);
const [form] = Form.useForm();
const submitAnyway = useRef<boolean>(false); const submitAnyway = useRef<boolean>(false);
const originFormData = useRef<any>(null); const originFormData = useRef<any>(null);
const handleClusterChange = (value: number) => {
getGPUOptionList({ clusterId: value });
};
const setOriginalFormData = () => { const setOriginalFormData = () => {
if (!originFormData.current) { if (!originFormData.current) {
originFormData.current = _.cloneDeep(formData); originFormData.current = _.cloneDeep(formData);
@@ -91,7 +75,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
}; };
const handleOnValuesChange = _.debounce((data: any) => { const handleOnValuesChange = _.debounce((data: any) => {
const formdata = form.getFieldsValue?.(); const formdata = formRef.current?.getFieldsValue?.();
console.log('handleOnValuesChange:', formdata); console.log('handleOnValuesChange:', formdata);
let alldata = {}; let alldata = {};
@@ -138,10 +122,11 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
// voxbox is not support multi gpu // voxbox is not support multi gpu
const handleSetGPUIds = (backend: string) => { const handleSetGPUIds = (backend: string) => {
const gpuids = form.getFieldValue(['gpu_selector', 'gpu_ids']) || []; const gpuids =
formRef.current?.getFieldValue(['gpu_selector', 'gpu_ids']) || [];
if (backend === backendOptionsMap.voxBox && gpuids.length > 0) { if (backend === backendOptionsMap.voxBox && gpuids.length > 0) {
form.setFieldValue(['gpu_selector', 'gpu_ids'], [gpuids[0]]); formRef.current?.setFieldValue(['gpu_selector', 'gpu_ids'], [gpuids[0]]);
} }
}; };
@@ -155,10 +140,14 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
cpu_offloading: true cpu_offloading: true
}); });
} }
form.setFieldsValue({ ...updates, backend_parameters: [], env: null }); formRef.current?.setFieldsValue({
...updates,
backend_parameters: [],
env: null
});
handleSetGPUIds(backend); handleSetGPUIds(backend);
const data = form.getFieldsValue?.(); const data = formRef.current?.getFieldsValue?.();
const res = handleBackendChangeBefore(data); const res = handleBackendChangeBefore(data);
if (res.show) { if (res.show) {
return; return;
@@ -185,23 +174,20 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
}; };
const handleSumit = () => { const handleSumit = () => {
form.submit(); formRef.current?.submit();
}; };
const handleSubmitAnyway = async () => { const handleSubmitAnyway = async () => {
submitAnyway.current = true; submitAnyway.current = true;
form.submit?.(); formRef.current?.submit?.();
}; };
const handleOk = async (data: FormData) => { const handleOk = async (formdata: FormData) => {
const formdata = getSourceRepoConfigValue(data.source, data).values;
let submitData = {} as FormData; let submitData = {} as FormData;
const isVoxBox = [backendOptionsMap.voxBox].includes(formdata.backend); const isVoxBox = [backendOptionsMap.voxBox].includes(formdata.backend);
submitData = { submitData = {
..._.omit(formdata, ['scheduleType']), ..._.omit(formdata, ['scheduleType']),
categories: formdata.categories ? [formdata.categories] : [],
worker_selector: worker_selector:
formdata.scheduleType === ScheduleValueMap.Manual formdata.scheduleType === ScheduleValueMap.Manual
? null ? null
@@ -211,25 +197,13 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
distributed_inference_across_workers: false, distributed_inference_across_workers: false,
cpu_offloading: false cpu_offloading: false
} }
: {}), : {})
...generateGPUIds(formdata)
}; };
onOk(submitData); onOk(submitData);
}; };
const onValuesChange = (changedValues: any, allValues: any) => {
const fieldName = Object.keys(changedValues)[0];
if (excludeFields.includes(fieldName)) {
return;
}
handleOnValuesChange({
changedValues,
allValues,
source: formData?.source as string
});
};
const handleManulOnValuesChange = (changedValues: any, allValues: any) => { const handleManulOnValuesChange = (changedValues: any, allValues: any) => {
console.log('handleManulOnValuesChange:', { changedValues, allValues });
handleOnValuesChange({ handleOnValuesChange({
changedValues, changedValues,
allValues, allValues,
@@ -249,17 +223,20 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
); );
}, [warningStatus.show, warningStatus.type, warningStatus.isDefault]); }, [warningStatus.show, warningStatus.type, warningStatus.isDefault]);
const isVllmOrAscend = useMemo(() => {
return (
formData?.backend === backendOptionsMap.vllm ||
formData?.backend === backendOptionsMap.ascendMindie
);
}, [formData?.backend]);
useEffect(() => { useEffect(() => {
const initGPUSelector = async () => {
const gpuOptions = await formRef.current?.getGPUOptionList({
clusterId: formData.cluster_id
});
const gpuSelector = generateGPUSelector(formData, gpuOptions);
formRef.current?.setFieldsValue(gpuSelector);
};
if (open && formData) { if (open && formData) {
setOriginalFormData(); setTimeout(() => {
getGPUOptionList({ clusterId: formData.cluster_id }); setOriginalFormData();
initGPUSelector();
}, 100);
} }
if (!open) { if (!open) {
checkTokenRef.current?.cancel?.(); checkTokenRef.current?.cancel?.();
@@ -339,109 +316,18 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
</> </>
} }
> >
<FormContext.Provider <DataForm
value={{ formKey={deployFormKeyMap.deployment}
isGGUF: isGGUF, initialValues={formData}
pageAction: action, source={formData.source || ''}
onValuesChange: handleManulOnValuesChange action={action}
}} clusterList={clusterList}
> onOk={handleOk}
<FormInnerContext.Provider ref={formRef}
value={{ isGGUF={isGGUF}
onBackendChange: handleBackendChange, onBackendChange={handleAsyncBackendChange}
gpuOptions: gpuOptions onValuesChange={handleManulOnValuesChange}
}} ></DataForm>
>
<Form
name="updateModalForm"
form={form}
onFinish={handleOk}
onValuesChange={onValuesChange}
scrollToFirstError={true}
preserve={false}
clearOnDestroy={true}
initialValues={{
...formData
}}
style={{
padding: 'var(--ant-modal-content-padding)',
paddingBlock: 0
}}
>
<Form.Item<FormData>
name="name"
rules={[
{
required: true,
message: getRuleMessage('input', 'common.table.name')
}
]}
>
<SealInput.Input
label={intl.formatMessage({
id: 'common.table.name'
})}
required
></SealInput.Input>
</Form.Item>
<Form.Item<FormData>
name="source"
rules={[
{
required: true,
message: getRuleMessage('select', 'models.form.source')
}
]}
>
<SealSelect
disabled={true}
label={intl.formatMessage({
id: 'models.form.source'
})}
options={sourceOptions}
required
></SealSelect>
</Form.Item>
<HuggingFaceForm></HuggingFaceForm>
<LocalPathForm></LocalPathForm>
<Form.Item<FormData>
name="cluster_id"
rules={[
{
required: true,
message: getRuleMessage('select', 'Cluster', false)
}
]}
>
{
<SealSelect
onChange={handleClusterChange}
label="Cluster"
options={clusterList}
required
></SealSelect>
}
</Form.Item>
<Form.Item<FormData> name="description">
<SealInput.TextArea
scaleSize={true}
label={intl.formatMessage({
id: 'common.table.description'
})}
></SealInput.TextArea>
</Form.Item>
<AdvanceConfig
form={form}
gpuOptions={gpuOptions}
action={PageAction.EDIT}
source={formData?.source || ''}
isGGUF={formData?.backend === backendOptionsMap.llamaBox}
></AdvanceConfig>
</Form>
</FormInnerContext.Provider>
</FormContext.Provider>
</ColumnWrapper> </ColumnWrapper>
</Modal> </Modal>
); );
+13 -14
View File
@@ -1,31 +1,30 @@
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import React from 'react'; import React from 'react';
import { DeployFormKey } from './types';
interface FormContextProps { interface FormContextProps {
isGGUF?: boolean; isGGUF?: boolean;
byBuiltIn?: boolean; formKey: DeployFormKey;
source?: string; source?: string;
pageAction: PageActionType; pageAction: PageActionType;
sizeOptions?: Global.BaseOption<number>[];
quantizationOptions?: Global.BaseOption<string>[];
gpuOptions?: any[]; gpuOptions?: any[];
onSizeChange?: (val: number) => void;
onQuantizationChange?: (val: string) => void;
onValuesChange?: (changedValues: any, allValues: any) => void; onValuesChange?: (changedValues: any, allValues: any) => void;
onBackendChange?: (backend: string) => void;
} }
interface FormInnerContextProps { interface CatalogFormContextProps {
onBackendChange?: (backend: string) => void; sizeOptions: Global.BaseOption<number>[];
onValuesChange?: (changedValues: any, allValues: any) => void; quantizationOptions: Global.BaseOption<string>[];
gpuOptions?: any[]; onSizeChange: (val: number) => void;
onQuantizationChange: (val: string) => void;
} }
export const FormContext = React.createContext<FormContextProps>( export const FormContext = React.createContext<FormContextProps>(
{} as FormContextProps {} as FormContextProps
); );
export const FormInnerContext = React.createContext<FormInnerContextProps>( export const CatalogFormContext = React.createContext<CatalogFormContextProps>(
{} as FormInnerContextProps {} as CatalogFormContextProps
); );
export const useFormContext = () => { export const useFormContext = () => {
@@ -36,11 +35,11 @@ export const useFormContext = () => {
return context; return context;
}; };
export const useFormInnerContext = () => { export const useCatalogFormContext = () => {
const context = React.useContext(FormInnerContext); const context = React.useContext(CatalogFormContext);
if (!context) { if (!context) {
throw new Error( throw new Error(
'useFormInnerContext must be used within a FormInnerProvider' 'useCatalogFormContext must be used within a CatalogFormProvider'
); );
} }
return context; return context;
+6 -54
View File
@@ -1,7 +1,7 @@
import { StatusMaps } from '@/config'; import { StatusMaps } from '@/config';
import { EditOutlined } from '@ant-design/icons'; import { EditOutlined } from '@ant-design/icons';
import _ from 'lodash';
import { backendOptionsMap } from './backend-parameters'; import { backendOptionsMap } from './backend-parameters';
import { DeployFormKey } from './types';
export const backendTipsList = [ export const backendTipsList = [
{ {
@@ -277,59 +277,6 @@ export const modelCategories = [
...categoryOptions ...categoryOptions
]; ];
export const sourceRepoConfig = {
[modelSourceMap.huggingface_value]: {
repo_id: 'huggingface_repo_id',
file_name: 'huggingface_filename'
},
[modelSourceMap.modelscope_value]: {
repo_id: 'model_scope_model_id',
file_name: 'model_scope_file_path'
}
};
export const getSourceRepoConfigValue = (
source: string,
data: any
): {
values: typeof data;
} => {
const config: Record<string, any> = sourceRepoConfig[source] || {};
const result: Record<string, any> = {};
const omits: string[] = [];
Object.keys(config)?.forEach((key: string) => {
if (config[key]) {
result[config[key]] = data[key];
omits.push(key);
}
});
return {
values: { ...result, ..._.omit(data, omits) }
};
};
export const setSourceRepoConfigValue = (
source: string,
data: any
): {
values: Record<string, any>;
} => {
const config: Record<string, any> = sourceRepoConfig[source] || {};
const result: Record<string, any> = {};
const omits: string[] = [];
Object.keys(config)?.forEach((key: string) => {
if (config[key]) {
result[key] = data[config[key]];
omits.push(config[key]);
}
});
return {
values: { ...result, ..._.omit(data, omits) }
};
};
export const getbackendParameters = (data: any) => { export const getbackendParameters = (data: any) => {
const backendParameters = data.backend_parameters || {}; const backendParameters = data.backend_parameters || {};
const result: string[] = []; const result: string[] = [];
@@ -487,3 +434,8 @@ export const scheduleTypeTips = [
tips: 'models.form.scheduletype.manual.tips' tips: 'models.form.scheduletype.manual.tips'
} }
]; ];
export const deployFormKeyMap: Record<string, DeployFormKey> = {
deployment: 'deployment',
catalog: 'catalog'
};
+3 -1
View File
@@ -30,6 +30,8 @@ export interface ListItem {
worker_selector?: object; worker_selector?: object;
} }
export type DeployFormKey = 'deployment' | 'catalog';
export type SourceType = export type SourceType =
| 'huggingface' | 'huggingface'
| 'model_scope' | 'model_scope'
@@ -45,7 +47,7 @@ export interface FormData {
categories?: string[]; categories?: string[];
backend_parameters?: string[]; backend_parameters?: string[];
backend_version?: string; backend_version?: string;
source: string; source: SourceType;
repo_id: string; repo_id: string;
file_name: string; file_name: string;
huggingface_repo_id: string; huggingface_repo_id: string;
+33
View File
@@ -0,0 +1,33 @@
import _ from 'lodash';
import { backendOptionsMap } from '../config/backend-parameters';
export const generateGPUSelector = (data: any, gpuOptions: any[]) => {
const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []);
if (gpu_ids.length === 0) {
return {
gpu_selector: null
};
}
const valueMap = new Map<string, string>();
gpuOptions?.forEach((item) => {
item.children?.forEach((child: any) => {
valueMap.set(child.value, item.value);
});
});
const gpuids: string[][] = gpu_ids
.map((id: string) => {
const parent = valueMap.get(id);
return parent ? [parent, id] : null;
})
.filter(Boolean) as string[][];
const result = data.backend === backendOptionsMap.voxBox ? gpuids[0] : gpuids;
return {
gpu_selector: {
gpu_ids: result
}
};
};
+10 -8
View File
@@ -2,25 +2,27 @@ import SealSelect from '@/components/seal-form/seal-select';
import useAppUtils from '@/hooks/use-app-utils'; import useAppUtils from '@/hooks/use-app-utils';
import { Form } from 'antd'; import { Form } from 'antd';
import React from 'react'; import React from 'react';
import { useFormContext } from '../config/form-context'; import { deployFormKeyMap } from '../config';
import { useCatalogFormContext, useFormContext } from '../config/form-context';
import { FormData } from '../config/types'; import { FormData } from '../config/types';
const CatalogForm: React.FC = () => { const CatalogForm: React.FC = () => {
const formCtx = useFormContext(); const formCtx = useFormContext();
const catalogFormCtx = useCatalogFormContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const { formKey } = formCtx;
const { const {
isGGUF,
byBuiltIn,
sizeOptions, sizeOptions,
quantizationOptions, quantizationOptions,
onSizeChange, onSizeChange,
onQuantizationChange onQuantizationChange
} = formCtx; } = catalogFormCtx;
const source = Form.useWatch('source');
console.log('HuggingFaceForm', { source, isGGUF }); if (
formKey !== deployFormKeyMap.catalog &&
if (!byBuiltIn && !sizeOptions?.length && !quantizationOptions?.length) { !sizeOptions?.length &&
!quantizationOptions?.length
) {
return null; return null;
} }
+62 -24
View File
@@ -1,10 +1,9 @@
import SealInput from '@/components/seal-form/seal-input'; import SealInput from '@/components/seal-form/seal-input';
import { PageAction } from '@/config'; import { PageAction } from '@/config';
import useAppUtils from '@/hooks/use-app-utils'; import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
import React from 'react'; import React from 'react';
import { modelSourceMap } from '../config'; import { deployFormKeyMap, modelSourceMap } from '../config';
import { useFormContext } from '../config/form-context'; import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types'; import { FormData } from '../config/types';
@@ -12,18 +11,15 @@ const HuggingFaceForm: React.FC = () => {
const formInstance = Form.useFormInstance(); const formInstance = Form.useFormInstance();
const formCtx = useFormContext(); const formCtx = useFormContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const intl = useIntl(); const { formKey, pageAction, onValuesChange } = formCtx;
const { isGGUF, byBuiltIn, pageAction, onValuesChange } = formCtx;
const source = Form.useWatch('source'); const source = Form.useWatch('source');
console.log('HuggingFaceForm', { source, isGGUF });
if ( if (
![ ![
modelSourceMap.huggingface_value, modelSourceMap.huggingface_value,
modelSourceMap.modelscope_value modelSourceMap.modelscope_value
].includes(source) || ].includes(source) ||
byBuiltIn formKey === deployFormKeyMap.catalog
) { ) {
return null; return null;
} }
@@ -34,23 +30,65 @@ const HuggingFaceForm: React.FC = () => {
return ( return (
<> <>
<Form.Item<FormData> {source === modelSourceMap.huggingface_value ? (
name="repo_id" <>
key="repo_id" <Form.Item<FormData>
rules={[ name="huggingface_repo_id"
{ key="huggingface_repo_id"
required: true, rules={[
message: getRuleMessage('input', 'models.form.repoid') {
} required: true,
]} message: getRuleMessage('input', 'models.form.repoid')
> }
<SealInput.Input ]}
label="Base Model" >
required <SealInput.Input
disabled={pageAction === PageAction.CREATE} label="Base Model"
onBlur={handleOnBlur} required
></SealInput.Input> disabled={pageAction === PageAction.CREATE}
</Form.Item> onBlur={handleOnBlur}
></SealInput.Input>
</Form.Item>
<Form.Item<FormData>
hidden
name="huggingface_filename"
key="huggingface_filename"
>
<SealInput.Input
disabled={pageAction === PageAction.CREATE}
></SealInput.Input>
</Form.Item>
</>
) : (
<>
<Form.Item<FormData>
name="model_scope_model_id"
key="model_scope_model_id"
rules={[
{
required: true,
message: getRuleMessage('input', 'models.form.repoid')
}
]}
>
<SealInput.Input
label="Base Model"
required
disabled={pageAction === PageAction.CREATE}
onBlur={handleOnBlur}
></SealInput.Input>
</Form.Item>
<Form.Item<FormData>
hidden
name="model_scope_file_path"
key="model_scope_file_path"
>
<SealInput.Input
disabled={pageAction === PageAction.CREATE}
></SealInput.Input>
</Form.Item>
</>
)}
</> </>
); );
}; };
+7 -6
View File
@@ -5,24 +5,25 @@ import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { localPathTipsList, modelSourceMap } from '../config'; import { deployFormKeyMap, localPathTipsList, modelSourceMap } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { useFormContext, useFormInnerContext } from '../config/form-context'; import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types'; import { FormData } from '../config/types';
import { checkOnlyAscendNPU } from '../hooks'; import { checkOnlyAscendNPU } from '../hooks';
const LocalPathForm: React.FC = () => { const LocalPathForm: React.FC = () => {
const form = Form.useFormInstance(); const form = Form.useFormInstance();
const formCtx = useFormContext(); const formCtx = useFormContext();
const formInnerCtx = useFormInnerContext();
const source = Form.useWatch('source', form); const source = Form.useWatch('source', form);
const { onBackendChange, onValuesChange, gpuOptions } = formInnerCtx; const { formKey, gpuOptions, onValuesChange, onBackendChange } = formCtx;
const { byBuiltIn } = formCtx;
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const intl = useIntl(); const intl = useIntl();
const localPathCache = useRef<string>(form.getFieldValue('local_path') || ''); const localPathCache = useRef<string>(form.getFieldValue('local_path') || '');
if (![modelSourceMap.local_path_value].includes(source) || byBuiltIn) { if (
![modelSourceMap.local_path_value].includes(source) ||
formKey === deployFormKeyMap.catalog
) {
return null; return null;
} }
+12 -11
View File
@@ -8,11 +8,7 @@ import { useAtomValue } from 'jotai';
import _ from 'lodash'; import _ from 'lodash';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { evaluationsModelSpec } from '../apis'; import { evaluationsModelSpec } from '../apis';
import { import { modelSourceMap, modelTaskMap } from '../config';
getSourceRepoConfigValue,
modelSourceMap,
modelTaskMap
} from '../config';
import { handleRecognizeAudioModel } from '../config/audio-catalog'; import { handleRecognizeAudioModel } from '../config/audio-catalog';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { EvaluateResult, FormData } from '../config/types'; import { EvaluateResult, FormData } from '../config/types';
@@ -394,6 +390,7 @@ export const useCheckCompatibility = () => {
const generateGPUIds = (data: FormData) => { const generateGPUIds = (data: FormData) => {
const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []); const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []);
console.log('generateGPUIds', gpu_ids);
if (!gpu_ids.length) { if (!gpu_ids.length) {
return { return {
gpu_selector: null gpu_selector: null
@@ -454,11 +451,10 @@ export const useCheckCompatibility = () => {
return; return;
} }
cacheFormValuesRef.current = allValues; cacheFormValuesRef.current = _.cloneDeep(allValues);
const data = getSourceRepoConfigValue(source, allValues); const gpuSelector = generateGPUIds(allValues);
const gpuSelector = generateGPUIds(data.values);
return await handleDoEvalute({ return await handleDoEvalute({
...data.values, ...allValues,
...gpuSelector, ...gpuSelector,
replicas: allValues.replicas || 0 replicas: allValues.replicas || 0
}); });
@@ -534,8 +530,13 @@ export const useSelectModel = (data: { gpuOptions: any[] }) => {
}); });
return { return {
repo_id: selectModel.name, ...(source === modelSourceMap.huggingface_value
file_name: '', ? { huggingface_repo_id: selectModel.name }
: {}),
...(source === modelSourceMap.modelscope_value
? { model_scope_model_id: selectModel.name }
: {}),
...modelTaskData,
name: name, name: name,
source: source, source: source,
backend: backend backend: backend
@@ -8,11 +8,9 @@ import {
} from '@/pages/resources/config'; } from '@/pages/resources/config';
import { ListItem as WorkerListItem } from '@/pages/resources/config/types'; import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import _ from 'lodash';
import { useState } from 'react'; import { useState } from 'react';
import { queryGPUList } from '../apis'; import { queryGPUList } from '../apis';
import { ScheduleValueMap, setSourceRepoConfigValue } from '../config'; import { ScheduleValueMap } from '../config';
import { backendOptionsMap } from '../config/backend-parameters';
import { GPUListItem, ListItem } from '../config/types'; import { GPUListItem, ListItem } from '../config/types';
type EmptyObject = Record<never, never>; type EmptyObject = Record<never, never>;
@@ -100,6 +98,7 @@ export const useGenerateGPUOptions = () => {
setGpuOptions(gpuList); setGpuOptions(gpuList);
return gpuList; return gpuList;
}; };
return { return {
getGPUOptionList, getGPUOptionList,
gpuOptions gpuOptions
@@ -190,7 +189,7 @@ export const useGenerateWorkerOptions = () => {
}; };
export default function useFormInitialValues() { export default function useFormInitialValues() {
const { getGPUOptionList } = useGenerateGPUOptions(); const { getGPUOptionList, gpuOptions } = useGenerateGPUOptions();
const [, setClusterListAtom] = useAtom(clusterListAtom); const [, setClusterListAtom] = useAtom(clusterListAtom);
const [clusterList, setClusterList] = useState< const [clusterList, setClusterList] = useState<
@@ -220,43 +219,13 @@ export default function useFormInitialValues() {
} }
}; };
const generateGPUSelector = (data: any, gpuOptions: any[]) => {
const gpu_ids = _.get(data, 'gpu_selector.gpu_ids', []);
if (gpu_ids.length === 0) {
return [];
}
const valueMap = new Map<string, string>();
gpuOptions?.forEach((item) => {
item.children?.forEach((child: any) => {
valueMap.set(child.value, item.value);
});
});
const gpuids: string[][] = gpu_ids
.map((id: string) => {
const parent = valueMap.get(id);
return parent ? [parent, id] : null;
})
.filter(Boolean) as string[][];
return data.backend === backendOptionsMap.voxBox ? gpuids[0] : gpuids;
};
const generateFormValues = (data: ListItem, gpuOptions: any[]) => { const generateFormValues = (data: ListItem, gpuOptions: any[]) => {
const result = setSourceRepoConfigValue(data?.source || '', data);
const formData = { const formData = {
...result.values, ...data,
categories: data?.categories?.length ? data.categories[0] : null, categories: data?.categories?.length ? data.categories[0] : null,
scheduleType: data?.gpu_selector scheduleType: data?.gpu_selector
? ScheduleValueMap.Manual ? ScheduleValueMap.Manual
: ScheduleValueMap.Auto, : ScheduleValueMap.Auto
gpu_selector: data?.gpu_selector?.gpu_ids?.length
? {
gpu_ids: generateGPUSelector(data, gpuOptions)
}
: null
}; };
return formData; return formData;
}; };
@@ -265,6 +234,7 @@ export default function useFormInitialValues() {
getGPUOptionList, getGPUOptionList,
generateFormValues, generateFormValues,
getClusterList, getClusterList,
clusterList clusterList,
gpuOptions
}; };
} }