refactor: advance collapse
This commit is contained in:
@@ -2,11 +2,23 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import React from 'react';
|
||||
import './style.less';
|
||||
|
||||
const ColumnWrapper: React.FC<any> = ({
|
||||
interface ColumnWrapperProps {
|
||||
children: React.ReactNode;
|
||||
footer?: React.ReactNode;
|
||||
maxHeight?: string | number;
|
||||
paddingBottom?: number;
|
||||
styles?: {
|
||||
wrapper?: React.CSSProperties;
|
||||
container?: React.CSSProperties;
|
||||
};
|
||||
}
|
||||
|
||||
const ColumnWrapper: React.FC<ColumnWrapperProps> = ({
|
||||
children,
|
||||
footer,
|
||||
maxHeight,
|
||||
paddingBottom = 50
|
||||
paddingBottom = 50,
|
||||
styles = {}
|
||||
}) => {
|
||||
const scroller = React.useRef<any>(null);
|
||||
const { initialize } = useOverlayScroller({
|
||||
@@ -27,12 +39,12 @@ const ColumnWrapper: React.FC<any> = ({
|
||||
<>
|
||||
<div
|
||||
className="column-wrapper-footer"
|
||||
style={{ height: maxHeight || '100%' }}
|
||||
style={{ height: maxHeight || '100%', ...styles.wrapper }}
|
||||
>
|
||||
<div
|
||||
className="column-wrapper"
|
||||
ref={scroller}
|
||||
style={{ padding: '16px 24px' }}
|
||||
style={{ padding: '16px 24px', ...styles.container }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -6,7 +6,7 @@ import { PageActionType } from '@/config/types';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Segmented, Tabs } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useEffect, useId, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import ColumnWrapper from '../../_components/column-wrapper';
|
||||
import { backendFields, json2Yaml } from '../config';
|
||||
@@ -46,6 +46,7 @@ interface AddModalProps {
|
||||
const AddModal: React.FC<AddModalProps> = (props) => {
|
||||
const { action, currentData, onClose, onSubmit, onSubmitYaml, open, title } =
|
||||
props;
|
||||
const uid = useId();
|
||||
const formRef = useRef<any>(null);
|
||||
const editorRef = useRef<any>(null);
|
||||
const intl = useIntl();
|
||||
@@ -121,7 +122,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
||||
setYamlContent(yaml);
|
||||
setFormContent(formData);
|
||||
formRef.current?.setFieldsValue?.(formData);
|
||||
editorRef.current?.setValue?.(yaml);
|
||||
editorRef.current?.setContent?.(yaml);
|
||||
}
|
||||
}, [action, currentData]);
|
||||
|
||||
@@ -129,6 +130,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
||||
<GSDrawer
|
||||
title={title}
|
||||
open={open}
|
||||
key={uid}
|
||||
onClose={onClose}
|
||||
destroyOnHidden={true}
|
||||
closeIcon={false}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import LabelSelector from '@/components/label-selector';
|
||||
import ListInput from '@/components/list-input';
|
||||
import CheckboxField from '@/components/seal-form/checkbox-field';
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
import TooltipList from '@/components/tooltip-list';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Collapse, Form, FormInstance, Typography } from 'antd';
|
||||
import { Collapse, Form, FormInstance } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
backendParamsHolderTips,
|
||||
getBackendParamsTips,
|
||||
modelCategories,
|
||||
placementStrategyOptions,
|
||||
@@ -21,9 +19,10 @@ import BackendParameters, {
|
||||
} from '../config/backend-parameters';
|
||||
import { useFormContext } from '../config/form-context';
|
||||
import { FormData } from '../config/types';
|
||||
import BackendFields from '../forms/backend-fields';
|
||||
import Backend from '../forms/backend';
|
||||
import BackendParametersList from '../forms/backend-parameters-list';
|
||||
import Performance from '../forms/performance';
|
||||
import dataformStyles from '../style/data-form.less';
|
||||
import Performance from './performance';
|
||||
|
||||
interface AdvanceConfigProps {
|
||||
isGGUF: boolean;
|
||||
@@ -44,9 +43,9 @@ const placementStrategyTips = [
|
||||
}
|
||||
];
|
||||
|
||||
const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
||||
const { form, isGGUF, gpuOptions, source, action } = props;
|
||||
const AdvanceConfig = () => {
|
||||
const intl = useIntl();
|
||||
const form = Form.useFormInstance();
|
||||
const wokerSelector = Form.useWatch('worker_selector', form);
|
||||
const EnviromentVars = Form.useWatch('env', form);
|
||||
const scheduleType = Form.useWatch('scheduleType', form);
|
||||
@@ -57,7 +56,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
||||
const placement_strategy = Form.useWatch('placement_strategy', form);
|
||||
const gpuSelectorIds = Form.useWatch(['gpu_selector', 'gpu_ids'], form);
|
||||
const worker_selector = Form.useWatch('worker_selector', form);
|
||||
const { onValuesChange } = useFormContext();
|
||||
const { onValuesChange, gpuOptions, source, isGGUF } = useFormContext();
|
||||
|
||||
const paramsConfig = useMemo(() => {
|
||||
return _.get(BackendParameters, backend, []);
|
||||
@@ -131,7 +130,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
||||
options={modelCategories}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
<BackendFields></BackendFields>
|
||||
<Backend></Backend>
|
||||
{scheduleType === ScheduleValueMap.Auto && (
|
||||
<>
|
||||
<Form.Item<FormData> name="placement_strategy">
|
||||
@@ -194,57 +193,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
||||
</>
|
||||
)}
|
||||
|
||||
<Form.Item<FormData> name="backend_parameters">
|
||||
<ListInput
|
||||
placeholder={
|
||||
backendParamsHolderTips[backend]
|
||||
? intl.formatMessage({
|
||||
id: backendParamsHolderTips[backend].holder
|
||||
})
|
||||
: ''
|
||||
}
|
||||
btnText={intl.formatMessage({ id: 'common.button.addParams' })}
|
||||
label={intl.formatMessage({
|
||||
id: 'models.form.backend_parameters'
|
||||
})}
|
||||
dataList={form.getFieldValue('backend_parameters') || []}
|
||||
onChange={handleBackendParametersChange}
|
||||
onBlur={handleBackendParametersOnBlur}
|
||||
onDelete={handleDeleteBackendParameters}
|
||||
options={paramsConfig}
|
||||
description={
|
||||
backendParamsTips.link && (
|
||||
<span>
|
||||
{backend === backendOptionsMap.ascendMindie && (
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'models.backend.mindie.310p' })}
|
||||
</span>
|
||||
)}
|
||||
<span style={{ marginLeft: 5 }}>
|
||||
{intl.formatMessage(
|
||||
{ id: 'models.form.backend_parameters.vllm.tips' },
|
||||
{ backend: backendParamsTips.backend || '' }
|
||||
)}{' '}
|
||||
<Typography.Link
|
||||
style={{ display: 'inline' }}
|
||||
className="flex-center"
|
||||
href={backendParamsTips.link}
|
||||
target="_blank"
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'common.text.here' })}
|
||||
</span>
|
||||
<IconFont
|
||||
type="icon-external-link"
|
||||
className="font-size-14 m-l-4"
|
||||
></IconFont>
|
||||
</Typography.Link>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
></ListInput>
|
||||
</Form.Item>
|
||||
<BackendParametersList></BackendParametersList>
|
||||
<Form.Item<FormData> name="env">
|
||||
<LabelSelector
|
||||
label={intl.formatMessage({
|
||||
@@ -313,19 +262,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
||||
forceRender: true,
|
||||
children: <Performance></Performance>
|
||||
},
|
||||
// {
|
||||
// key: '3',
|
||||
// label: (
|
||||
// <span
|
||||
// style={{ fontWeight: 'var(--font-weight-medium)' }}
|
||||
// className="font-size-14"
|
||||
// >
|
||||
// Scaling
|
||||
// </span>
|
||||
// ),
|
||||
// forceRender: true,
|
||||
// children: <Scaling></Scaling>
|
||||
// },
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
|
||||
@@ -2,6 +2,7 @@ import SealInput from '@/components/seal-form/seal-input';
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import useAppUtils from '@/hooks/use-app-utils';
|
||||
import CollapsePanel from '@/pages/_components/collapse-panel';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import _ from 'lodash';
|
||||
@@ -17,10 +18,12 @@ import {
|
||||
} from '../config/types';
|
||||
import { generateGPUIds } from '../config/utils';
|
||||
import CatalogFrom from '../forms/catalog';
|
||||
import HuggingFaceForm from '../forms/hugging-face';
|
||||
import LocalPathForm from '../forms/local-path';
|
||||
import LocalPathSource from '../forms/local-path-source';
|
||||
import OnlineSource from '../forms/online-source';
|
||||
import { useGenerateGPUOptions } from '../hooks/use-form-initial-values';
|
||||
import AdvanceConfig from './advance-config';
|
||||
// import AdvanceConfig from './advance-config';
|
||||
import AdvanceConfig from '../forms/advance-config';
|
||||
import Performance from '../forms/performance';
|
||||
|
||||
interface DataFormProps {
|
||||
initialValues?: any;
|
||||
@@ -59,6 +62,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
const { getRuleMessage } = useAppUtils();
|
||||
const [form] = Form.useForm();
|
||||
const intl = useIntl();
|
||||
const [activeKey, setActiveKey] = React.useState<string[]>([]);
|
||||
|
||||
const handleSumit = () => {
|
||||
form.submit();
|
||||
@@ -118,6 +122,10 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
onValuesChange?.(changedValues, allValues);
|
||||
};
|
||||
|
||||
const handleOnCollapseChange = (keys: string | string[]) => {
|
||||
setActiveKey(Array.isArray(keys) ? keys : [keys]);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
form: form,
|
||||
@@ -216,8 +224,8 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<HuggingFaceForm></HuggingFaceForm>
|
||||
<LocalPathForm></LocalPathForm>
|
||||
<OnlineSource></OnlineSource>
|
||||
<LocalPathSource></LocalPathSource>
|
||||
<Form.Item<FormData>
|
||||
name="cluster_id"
|
||||
rules={[
|
||||
@@ -245,13 +253,25 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
||||
})}
|
||||
></SealInput.TextArea>
|
||||
</Form.Item>
|
||||
<AdvanceConfig
|
||||
form={form}
|
||||
gpuOptions={gpuOptions}
|
||||
isGGUF={isGGUF}
|
||||
action={action}
|
||||
source={props.source}
|
||||
></AdvanceConfig>
|
||||
<CollapsePanel
|
||||
activeKey={activeKey}
|
||||
accordion={false}
|
||||
onChange={handleOnCollapseChange}
|
||||
items={[
|
||||
{
|
||||
key: 'performance',
|
||||
label: 'Performance',
|
||||
forceRender: true,
|
||||
children: <Performance></Performance>
|
||||
},
|
||||
{
|
||||
key: 'advance_config',
|
||||
label: 'Advanced',
|
||||
forceRender: true,
|
||||
children: <AdvanceConfig></AdvanceConfig>
|
||||
}
|
||||
]}
|
||||
></CollapsePanel>
|
||||
</Form>
|
||||
</FormContext.Provider>
|
||||
);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { Col, Row } from 'antd';
|
||||
import React from 'react';
|
||||
import '../style/deploy-dropdown.less';
|
||||
|
||||
interface DeployDropdownProps {
|
||||
items: { label: string; value: string; key: string; icon: React.ReactNode }[];
|
||||
onSelect: (item: {
|
||||
label: string;
|
||||
value: string;
|
||||
key: string;
|
||||
icon: React.ReactNode;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
const DeployDropdown: React.FC<DeployDropdownProps> = ({ items, onSelect }) => {
|
||||
return (
|
||||
<div className="deploy-dropdown">
|
||||
<Row gutter={[0, 16]}>
|
||||
{items.map((item) => (
|
||||
<Col span={8} key={item.key}>
|
||||
<div key={item.key} onClick={() => onSelect(item)} className="item">
|
||||
<span className="icon">{item.icon}</span>
|
||||
<span className="label">{item.label}</span>
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployDropdown;
|
||||
@@ -36,10 +36,15 @@ const ModalFooterStyle = {
|
||||
justifyContent: 'flex-end'
|
||||
};
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const ColWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
maxwidth: 33.33%;
|
||||
max-width: 33.33%;
|
||||
`;
|
||||
|
||||
const FormWrapper = styled.div`
|
||||
@@ -445,31 +450,27 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
width={width}
|
||||
footer={false}
|
||||
>
|
||||
<div style={{ display: 'flex', height: '100%' }}>
|
||||
<Container>
|
||||
{SEARCH_SOURCE.includes(props.source) &&
|
||||
deploymentType === 'modelList' && (
|
||||
<>
|
||||
<ColWrapper>
|
||||
<ColumnWrapper>
|
||||
<SearchModel
|
||||
hasLinuxWorker={hasLinuxWorker}
|
||||
modelSource={props.source}
|
||||
onSelectModel={handleOnSelectModel}
|
||||
onSelectModelAfterEvaluate={
|
||||
handleOnSelectModelAfterEvaluate
|
||||
}
|
||||
clusterId={
|
||||
form.current?.getFieldValue?.('cluster_id') ||
|
||||
initClusterId()
|
||||
}
|
||||
displayEvaluateStatus={displayEvaluateStatus}
|
||||
gpuOptions={[]}
|
||||
></SearchModel>
|
||||
</ColumnWrapper>
|
||||
<SearchModel
|
||||
hasLinuxWorker={hasLinuxWorker}
|
||||
modelSource={props.source}
|
||||
onSelectModel={handleOnSelectModel}
|
||||
onSelectModelAfterEvaluate={handleOnSelectModelAfterEvaluate}
|
||||
clusterId={
|
||||
form.current?.getFieldValue?.('cluster_id') ||
|
||||
initClusterId()
|
||||
}
|
||||
displayEvaluateStatus={displayEvaluateStatus}
|
||||
gpuOptions={[]}
|
||||
></SearchModel>
|
||||
<Separator></Separator>
|
||||
</ColWrapper>
|
||||
<ColWrapper>
|
||||
<ColumnWrapper>
|
||||
<ColumnWrapper styles={{ container: { paddingTop: 0 } }}>
|
||||
<ModelCard
|
||||
selectedModel={selectedModel}
|
||||
onCollapse={setCollapsed}
|
||||
@@ -545,7 +546,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
||||
</>
|
||||
</ColumnWrapper>
|
||||
</FormWrapper>
|
||||
</div>
|
||||
</Container>
|
||||
</GSDrawer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getRequestId, setRquestId } from '@/atoms/models';
|
||||
import BaseSelect from '@/components/seal-form/base/select';
|
||||
import { createAxiosToken } from '@/hooks/use-chunk-request';
|
||||
import ColumnWrapper from '@/pages/_components/column-wrapper';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Pagination } from 'antd';
|
||||
import _ from 'lodash';
|
||||
@@ -521,11 +522,11 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
||||
onChange={handleSearchInputChange}
|
||||
modelSource={modelSource}
|
||||
></SearchInput>
|
||||
<div className="gguf-tips">
|
||||
{/* <div className="gguf-tips">
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'models.form.search.gguftips' })}
|
||||
</span>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className={SearchStyle.filter}>
|
||||
<span className="flex-center gap-8">
|
||||
<BaseSelect
|
||||
@@ -582,18 +583,19 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ flex: 1 }}>
|
||||
<div style={{ width: '100%' }}>
|
||||
<div className={SearchStyle['search-bar']}>{renderHFSearch()}</div>
|
||||
|
||||
<SearchResult
|
||||
loading={dataSource.loading}
|
||||
resultList={dataSource.dataList}
|
||||
networkError={dataSource.networkError}
|
||||
current={current}
|
||||
source={modelSource}
|
||||
isEvaluating={isEvaluating}
|
||||
onSelect={handleSelectModelManually}
|
||||
></SearchResult>
|
||||
<ColumnWrapper maxHeight={'calc(100vh - 210px)'}>
|
||||
<SearchResult
|
||||
loading={dataSource.loading}
|
||||
resultList={dataSource.dataList}
|
||||
networkError={dataSource.networkError}
|
||||
current={current}
|
||||
source={modelSource}
|
||||
isEvaluating={isEvaluating}
|
||||
onSelect={handleSelectModelManually}
|
||||
></SearchResult>
|
||||
</ColumnWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import SimpleOverlay from '@/components/simple-overlay';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Empty, Spin } from 'antd';
|
||||
@@ -121,7 +120,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
|
||||
}, [networkError, source, intl]);
|
||||
|
||||
return (
|
||||
<SimpleOverlay style={{ height: 'calc(100vh - 224px)' }}>
|
||||
<>
|
||||
<div style={{ ...props.style }} className="search-result-wrap">
|
||||
<Spin spinning={props.loading}>
|
||||
<div style={{ minHeight: 200 }}>
|
||||
@@ -167,7 +166,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</SimpleOverlay>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ interface FormContextProps {
|
||||
formKey: DeployFormKey;
|
||||
source: string;
|
||||
pageAction: PageActionType;
|
||||
gpuOptions?: any[];
|
||||
gpuOptions: any[];
|
||||
backendOptions: BackendOption[];
|
||||
onValuesChange?: (changedValues: any, allValues: any) => void;
|
||||
onBackendChange: (backend: string, option: any) => void;
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
import LabelSelector from '@/components/label-selector';
|
||||
import CheckboxField from '@/components/seal-form/checkbox-field';
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
import TooltipList from '@/components/tooltip-list';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import { useCallback } from 'react';
|
||||
import {
|
||||
modelCategories,
|
||||
placementStrategyOptions,
|
||||
ScheduleValueMap
|
||||
} from '../config';
|
||||
import { backendOptionsMap } from '../config/backend-parameters';
|
||||
import { useFormContext } from '../config/form-context';
|
||||
import { FormData } from '../config/types';
|
||||
import Backend from '../forms/backend';
|
||||
import BackendParametersList from '../forms/backend-parameters-list';
|
||||
|
||||
const placementStrategyTips = [
|
||||
{
|
||||
title: 'Spread',
|
||||
tips: 'resources.form.spread.tips'
|
||||
},
|
||||
{
|
||||
title: 'Binpack',
|
||||
tips: 'resources.form.binpack.tips'
|
||||
}
|
||||
];
|
||||
|
||||
const AdvanceConfig = () => {
|
||||
const intl = useIntl();
|
||||
const form = Form.useFormInstance();
|
||||
const wokerSelector = Form.useWatch('worker_selector', form);
|
||||
const EnviromentVars = Form.useWatch('env', form);
|
||||
const scheduleType = Form.useWatch('scheduleType', form);
|
||||
const backend = Form.useWatch('backend', form);
|
||||
const { onValuesChange } = useFormContext();
|
||||
|
||||
const handleWorkerLabelsChange = useCallback(
|
||||
(labels: Record<string, any>) => {
|
||||
form.setFieldValue('worker_selector', labels);
|
||||
},
|
||||
[]
|
||||
);
|
||||
const handleEnviromentVarsChange = useCallback(
|
||||
(labels: Record<string, any>) => {
|
||||
form.setFieldValue('env', labels);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const onSelectorChange = (field: string, allowEmpty?: boolean) => {
|
||||
const workerSelector = form.getFieldValue(field);
|
||||
// check if all keys have values
|
||||
const hasEmptyValue = _.some(_.keys(workerSelector), (k: string) => {
|
||||
return !workerSelector[k];
|
||||
});
|
||||
if (!hasEmptyValue || allowEmpty) {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectorOnBlur = () => {
|
||||
onSelectorChange('worker_selector');
|
||||
};
|
||||
|
||||
const handleDeleteWorkerSelector = (index: number) => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
const handleEnvSelectorOnBlur = () => {
|
||||
onSelectorChange('env', true);
|
||||
};
|
||||
|
||||
const handleDeleteEnvSelector = (index: number) => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item<FormData> name="categories">
|
||||
<SealSelect
|
||||
allowNull
|
||||
label={intl.formatMessage({
|
||||
id: 'models.form.categories'
|
||||
})}
|
||||
options={modelCategories}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
<Backend></Backend>
|
||||
{scheduleType === ScheduleValueMap.Auto && (
|
||||
<>
|
||||
<Form.Item<FormData> name="placement_strategy">
|
||||
<SealSelect
|
||||
label={intl.formatMessage({
|
||||
id: 'resources.form.placementStrategy'
|
||||
})}
|
||||
options={placementStrategyOptions}
|
||||
description={
|
||||
<TooltipList list={placementStrategyTips}></TooltipList>
|
||||
}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
<Form.Item<FormData>
|
||||
name="worker_selector"
|
||||
rules={[
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
getFieldValue('scheduleType') === ScheduleValueMap.Auto &&
|
||||
_.keys(value).length > 0
|
||||
) {
|
||||
if (_.some(_.keys(value), (k: string) => !value[k])) {
|
||||
return Promise.reject(
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: 'common.validate.value'
|
||||
},
|
||||
{
|
||||
name: intl.formatMessage({
|
||||
id: 'models.form.selector'
|
||||
})
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
})
|
||||
]}
|
||||
>
|
||||
<LabelSelector
|
||||
label={intl.formatMessage({
|
||||
id: 'resources.form.workerSelector'
|
||||
})}
|
||||
labels={wokerSelector}
|
||||
onChange={handleWorkerLabelsChange}
|
||||
onBlur={handleSelectorOnBlur}
|
||||
onDelete={handleDeleteWorkerSelector}
|
||||
description={
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: 'resources.form.workerSelector.description'
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
></LabelSelector>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
|
||||
<BackendParametersList></BackendParametersList>
|
||||
<Form.Item<FormData> name="env">
|
||||
<LabelSelector
|
||||
label={intl.formatMessage({
|
||||
id: 'models.form.env'
|
||||
})}
|
||||
labels={EnviromentVars}
|
||||
btnText={intl.formatMessage({ id: 'common.button.vars' })}
|
||||
onBlur={handleEnvSelectorOnBlur}
|
||||
onDelete={handleDeleteEnvSelector}
|
||||
onChange={handleEnviromentVarsChange}
|
||||
></LabelSelector>
|
||||
</Form.Item>
|
||||
|
||||
{scheduleType === ScheduleValueMap.Auto &&
|
||||
[backendOptionsMap.vllm, backendOptionsMap.ascendMindie].includes(
|
||||
backend
|
||||
) && (
|
||||
<div style={{ paddingBottom: 22, paddingLeft: 10 }}>
|
||||
<Form.Item<FormData>
|
||||
name="distributed_inference_across_workers"
|
||||
valuePropName="checked"
|
||||
style={{ padding: '0 10px', marginBottom: 0 }}
|
||||
noStyle
|
||||
>
|
||||
<CheckboxField
|
||||
description={intl.formatMessage({
|
||||
id: 'models.form.distribution.tips'
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
id: 'resources.form.enableDistributedInferenceAcrossWorkers'
|
||||
})}
|
||||
></CheckboxField>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ paddingBottom: 22, paddingLeft: 10 }}>
|
||||
<Form.Item<FormData>
|
||||
name="restart_on_error"
|
||||
valuePropName="checked"
|
||||
style={{ padding: '0 10px', marginBottom: 0 }}
|
||||
noStyle
|
||||
>
|
||||
<CheckboxField
|
||||
description={intl.formatMessage({
|
||||
id: 'models.form.restart.onerror.tips'
|
||||
})}
|
||||
label={intl.formatMessage({
|
||||
id: 'models.form.restart.onerror'
|
||||
})}
|
||||
></CheckboxField>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdvanceConfig;
|
||||
@@ -0,0 +1,93 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import ListInput from '@/components/list-input';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form, Typography } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { backendParamsHolderTips, getBackendParamsTips } from '../config';
|
||||
import BackendParameters, {
|
||||
backendOptionsMap
|
||||
} from '../config/backend-parameters';
|
||||
import { useFormContext } from '../config/form-context';
|
||||
import { FormData } from '../config/types';
|
||||
|
||||
const BackendParametersList: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const { onValuesChange } = useFormContext();
|
||||
const form = Form.useFormInstance();
|
||||
const backend = Form.useWatch('backend', form);
|
||||
|
||||
const backendParamsTips = useMemo(() => {
|
||||
return getBackendParamsTips(backend);
|
||||
}, [backend]);
|
||||
|
||||
const paramsConfig = useMemo(() => {
|
||||
return _.get(BackendParameters, backend, []);
|
||||
}, [backend]);
|
||||
|
||||
const handleBackendParametersChange = (list: string[]) => {
|
||||
form.setFieldValue('backend_parameters', list);
|
||||
};
|
||||
|
||||
const handleBackendParametersOnBlur = () => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
const handleDeleteBackendParameters = (index: number) => {
|
||||
onValuesChange?.({}, form.getFieldsValue());
|
||||
};
|
||||
|
||||
return (
|
||||
<Form.Item<FormData> name="backend_parameters">
|
||||
<ListInput
|
||||
placeholder={
|
||||
backendParamsHolderTips[backend]
|
||||
? intl.formatMessage({
|
||||
id: backendParamsHolderTips[backend].holder
|
||||
})
|
||||
: ''
|
||||
}
|
||||
btnText={intl.formatMessage({ id: 'common.button.addParams' })}
|
||||
label={intl.formatMessage({
|
||||
id: 'models.form.backend_parameters'
|
||||
})}
|
||||
dataList={form.getFieldValue('backend_parameters') || []}
|
||||
onChange={handleBackendParametersChange}
|
||||
onBlur={handleBackendParametersOnBlur}
|
||||
onDelete={handleDeleteBackendParameters}
|
||||
options={paramsConfig}
|
||||
description={
|
||||
backendParamsTips.link && (
|
||||
<span>
|
||||
{backend === backendOptionsMap.ascendMindie && (
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'models.backend.mindie.310p' })}
|
||||
</span>
|
||||
)}
|
||||
<span style={{ marginLeft: 5 }}>
|
||||
{intl.formatMessage(
|
||||
{ id: 'models.form.backend_parameters.vllm.tips' },
|
||||
{ backend: backendParamsTips.backend || '' }
|
||||
)}{' '}
|
||||
<Typography.Link
|
||||
style={{ display: 'inline' }}
|
||||
className="flex-center"
|
||||
href={backendParamsTips.link}
|
||||
target="_blank"
|
||||
>
|
||||
<span>{intl.formatMessage({ id: 'common.text.here' })}</span>
|
||||
<IconFont
|
||||
type="icon-external-link"
|
||||
className="font-size-14 m-l-4"
|
||||
></IconFont>
|
||||
</Typography.Link>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
></ListInput>
|
||||
</Form.Item>
|
||||
);
|
||||
};
|
||||
|
||||
export default BackendParametersList;
|
||||
+9
-3
@@ -14,9 +14,14 @@ import useCheckBackend from '../hooks/use-check-backend';
|
||||
const LocalPathForm: React.FC = () => {
|
||||
const { checkOnlyAscendNPU } = useCheckBackend();
|
||||
const form = Form.useFormInstance();
|
||||
const formCtx = useFormContext();
|
||||
const source = Form.useWatch('source', form);
|
||||
const { formKey, gpuOptions, onValuesChange, onBackendChange } = formCtx;
|
||||
const {
|
||||
formKey,
|
||||
gpuOptions,
|
||||
backendOptions,
|
||||
onValuesChange,
|
||||
onBackendChange
|
||||
} = useFormContext();
|
||||
const { getRuleMessage } = useAppUtils();
|
||||
const intl = useIntl();
|
||||
const localPathCache = useRef<string>(form.getFieldValue('local_path') || '');
|
||||
@@ -58,7 +63,8 @@ const LocalPathForm: React.FC = () => {
|
||||
});
|
||||
|
||||
if (oldBackend !== backend) {
|
||||
onBackendChange?.(backend);
|
||||
const option = backendOptions.find((item) => item.value === backend);
|
||||
onBackendChange?.(backend, option);
|
||||
} else {
|
||||
onValuesChange?.({ local_path: value }, form.getFieldsValue());
|
||||
}
|
||||
+1
-1
@@ -5,10 +5,10 @@ import useAppUtils from '@/hooks/use-app-utils';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import React from 'react';
|
||||
import GPUCard from '../components/gpu-card';
|
||||
import { scheduleList, ScheduleValueMap } from '../config';
|
||||
import { backendOptionsMap } from '../config/backend-parameters';
|
||||
import { useCatalogFormContext, useFormContext } from '../config/form-context';
|
||||
import GPUCard from './gpu-card';
|
||||
|
||||
const scheduleTypeTips = [
|
||||
{
|
||||
@@ -26,8 +26,3 @@
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.card-wrapper {
|
||||
padding: 16px 24px;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@padding: 24px;
|
||||
|
||||
.search-result-wrap {
|
||||
padding: 16px @padding;
|
||||
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
|
||||
|
||||
.ant-spin-container.ant-spin-blur {
|
||||
@@ -21,8 +20,6 @@
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding-inline: @padding;
|
||||
background: var(--ant-color-bg-elevated);
|
||||
padding-bottom: 10px;
|
||||
@@ -32,6 +29,8 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
row-gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
color: var(--ant-color-text-tertiary);
|
||||
|
||||
:global {
|
||||
|
||||
Reference in New Issue
Block a user