refactor: advance collapse

This commit is contained in:
jialin
2025-10-13 14:40:26 +08:00
parent a5c1b8e15f
commit 46ecc2467b
18 changed files with 423 additions and 177 deletions
+6 -4
View File
@@ -58,12 +58,14 @@ export default defineConfig({
.filename(`js/[name].${t}.js`) .filename(`js/[name].${t}.js`)
.chunkFilename(`js/[name].${t}.chunk.js`); .chunkFilename(`js/[name].${t}.chunk.js`);
compressionPluginConfig(config); compressionPluginConfig(config);
monacoPluginConfig(config);
} }
} }
: {}), : {
chainWebpack(config) { chainWebpack(config) {
monacoPluginConfig(config); monacoPluginConfig(config);
}, }
}),
favicons: ['/static/favicon.png'], favicons: ['/static/favicon.png'],
jsMinifier: 'terser', jsMinifier: 'terser',
cssMinifier: 'cssnano', cssMinifier: 'cssnano',
+16 -4
View File
@@ -2,11 +2,23 @@ import useOverlayScroller from '@/hooks/use-overlay-scroller';
import React from 'react'; import React from 'react';
import './style.less'; 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, children,
footer, footer,
maxHeight, maxHeight,
paddingBottom = 50 paddingBottom = 50,
styles = {}
}) => { }) => {
const scroller = React.useRef<any>(null); const scroller = React.useRef<any>(null);
const { initialize } = useOverlayScroller({ const { initialize } = useOverlayScroller({
@@ -27,12 +39,12 @@ const ColumnWrapper: React.FC<any> = ({
<> <>
<div <div
className="column-wrapper-footer" className="column-wrapper-footer"
style={{ height: maxHeight || '100%' }} style={{ height: maxHeight || '100%', ...styles.wrapper }}
> >
<div <div
className="column-wrapper" className="column-wrapper"
ref={scroller} ref={scroller}
style={{ padding: '16px 24px' }} style={{ padding: '16px 24px', ...styles.container }}
> >
<div <div
style={{ style={{
+4 -2
View File
@@ -6,7 +6,7 @@ import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Segmented, Tabs } from 'antd'; import { Segmented, Tabs } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useId, useRef, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import ColumnWrapper from '../../_components/column-wrapper'; import ColumnWrapper from '../../_components/column-wrapper';
import { backendFields, json2Yaml } from '../config'; import { backendFields, json2Yaml } from '../config';
@@ -46,6 +46,7 @@ interface AddModalProps {
const AddModal: React.FC<AddModalProps> = (props) => { const AddModal: React.FC<AddModalProps> = (props) => {
const { action, currentData, onClose, onSubmit, onSubmitYaml, open, title } = const { action, currentData, onClose, onSubmit, onSubmitYaml, open, title } =
props; props;
const uid = useId();
const formRef = useRef<any>(null); const formRef = useRef<any>(null);
const editorRef = useRef<any>(null); const editorRef = useRef<any>(null);
const intl = useIntl(); const intl = useIntl();
@@ -121,7 +122,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
setYamlContent(yaml); setYamlContent(yaml);
setFormContent(formData); setFormContent(formData);
formRef.current?.setFieldsValue?.(formData); formRef.current?.setFieldsValue?.(formData);
editorRef.current?.setValue?.(yaml); editorRef.current?.setContent?.(yaml);
} }
}, [action, currentData]); }, [action, currentData]);
@@ -129,6 +130,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
<GSDrawer <GSDrawer
title={title} title={title}
open={open} open={open}
key={uid}
onClose={onClose} onClose={onClose}
destroyOnHidden={true} destroyOnHidden={true}
closeIcon={false} closeIcon={false}
@@ -1,16 +1,14 @@
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import LabelSelector from '@/components/label-selector'; import LabelSelector from '@/components/label-selector';
import ListInput from '@/components/list-input';
import CheckboxField from '@/components/seal-form/checkbox-field'; import CheckboxField from '@/components/seal-form/checkbox-field';
import SealSelect from '@/components/seal-form/seal-select'; import SealSelect from '@/components/seal-form/seal-select';
import TooltipList from '@/components/tooltip-list'; import TooltipList from '@/components/tooltip-list';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Collapse, Form, FormInstance, Typography } from 'antd'; import { Collapse, Form, FormInstance } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { import {
backendParamsHolderTips,
getBackendParamsTips, getBackendParamsTips,
modelCategories, modelCategories,
placementStrategyOptions, placementStrategyOptions,
@@ -21,9 +19,10 @@ import BackendParameters, {
} from '../config/backend-parameters'; } from '../config/backend-parameters';
import { useFormContext } from '../config/form-context'; import { useFormContext } from '../config/form-context';
import { FormData } from '../config/types'; 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 dataformStyles from '../style/data-form.less';
import Performance from './performance';
interface AdvanceConfigProps { interface AdvanceConfigProps {
isGGUF: boolean; isGGUF: boolean;
@@ -44,9 +43,9 @@ const placementStrategyTips = [
} }
]; ];
const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => { const AdvanceConfig = () => {
const { form, isGGUF, gpuOptions, source, action } = props;
const intl = useIntl(); const intl = useIntl();
const form = Form.useFormInstance();
const wokerSelector = Form.useWatch('worker_selector', form); const wokerSelector = Form.useWatch('worker_selector', form);
const EnviromentVars = Form.useWatch('env', form); const EnviromentVars = Form.useWatch('env', form);
const scheduleType = Form.useWatch('scheduleType', 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 placement_strategy = Form.useWatch('placement_strategy', form);
const gpuSelectorIds = Form.useWatch(['gpu_selector', 'gpu_ids'], form); const gpuSelectorIds = Form.useWatch(['gpu_selector', 'gpu_ids'], form);
const worker_selector = Form.useWatch('worker_selector', form); const worker_selector = Form.useWatch('worker_selector', form);
const { onValuesChange } = useFormContext(); const { onValuesChange, gpuOptions, source, isGGUF } = useFormContext();
const paramsConfig = useMemo(() => { const paramsConfig = useMemo(() => {
return _.get(BackendParameters, backend, []); return _.get(BackendParameters, backend, []);
@@ -131,7 +130,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
options={modelCategories} options={modelCategories}
></SealSelect> ></SealSelect>
</Form.Item> </Form.Item>
<BackendFields></BackendFields> <Backend></Backend>
{scheduleType === ScheduleValueMap.Auto && ( {scheduleType === ScheduleValueMap.Auto && (
<> <>
<Form.Item<FormData> name="placement_strategy"> <Form.Item<FormData> name="placement_strategy">
@@ -194,57 +193,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
</> </>
)} )}
<Form.Item<FormData> name="backend_parameters"> <BackendParametersList></BackendParametersList>
<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>
<Form.Item<FormData> name="env"> <Form.Item<FormData> name="env">
<LabelSelector <LabelSelector
label={intl.formatMessage({ label={intl.formatMessage({
@@ -313,19 +262,6 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
forceRender: true, forceRender: true,
children: <Performance></Performance> 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', key: '1',
label: ( label: (
+32 -12
View File
@@ -2,6 +2,7 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select'; import SealSelect from '@/components/seal-form/seal-select';
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 CollapsePanel from '@/pages/_components/collapse-panel';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
@@ -17,10 +18,12 @@ import {
} from '../config/types'; } from '../config/types';
import { generateGPUIds } from '../config/utils'; import { generateGPUIds } from '../config/utils';
import CatalogFrom from '../forms/catalog'; import CatalogFrom from '../forms/catalog';
import HuggingFaceForm from '../forms/hugging-face'; import LocalPathSource from '../forms/local-path-source';
import LocalPathForm from '../forms/local-path'; import OnlineSource from '../forms/online-source';
import { useGenerateGPUOptions } from '../hooks/use-form-initial-values'; 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 { interface DataFormProps {
initialValues?: any; initialValues?: any;
@@ -59,6 +62,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const [form] = Form.useForm(); const [form] = Form.useForm();
const intl = useIntl(); const intl = useIntl();
const [activeKey, setActiveKey] = React.useState<string[]>([]);
const handleSumit = () => { const handleSumit = () => {
form.submit(); form.submit();
@@ -118,6 +122,10 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
onValuesChange?.(changedValues, allValues); onValuesChange?.(changedValues, allValues);
}; };
const handleOnCollapseChange = (keys: string | string[]) => {
setActiveKey(Array.isArray(keys) ? keys : [keys]);
};
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
form: form, form: form,
@@ -216,8 +224,8 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
</Form.Item> </Form.Item>
)} )}
<HuggingFaceForm></HuggingFaceForm> <OnlineSource></OnlineSource>
<LocalPathForm></LocalPathForm> <LocalPathSource></LocalPathSource>
<Form.Item<FormData> <Form.Item<FormData>
name="cluster_id" name="cluster_id"
rules={[ rules={[
@@ -245,13 +253,25 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
})} })}
></SealInput.TextArea> ></SealInput.TextArea>
</Form.Item> </Form.Item>
<AdvanceConfig <CollapsePanel
form={form} activeKey={activeKey}
gpuOptions={gpuOptions} accordion={false}
isGGUF={isGGUF} onChange={handleOnCollapseChange}
action={action} items={[
source={props.source} {
></AdvanceConfig> key: 'performance',
label: 'Performance',
forceRender: true,
children: <Performance></Performance>
},
{
key: 'advance_config',
label: 'Advanced',
forceRender: true,
children: <AdvanceConfig></AdvanceConfig>
}
]}
></CollapsePanel>
</Form> </Form>
</FormContext.Provider> </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;
+21 -20
View File
@@ -36,10 +36,15 @@ const ModalFooterStyle = {
justifyContent: 'flex-end' justifyContent: 'flex-end'
}; };
const Container = styled.div`
display: flex;
height: 100%;
`;
const ColWrapper = styled.div` const ColWrapper = styled.div`
display: flex; display: flex;
flex: 1; flex: 1;
maxwidth: 33.33%; max-width: 33.33%;
`; `;
const FormWrapper = styled.div` const FormWrapper = styled.div`
@@ -445,31 +450,27 @@ const AddModal: FC<AddModalProps> = (props) => {
width={width} width={width}
footer={false} footer={false}
> >
<div style={{ display: 'flex', height: '100%' }}> <Container>
{SEARCH_SOURCE.includes(props.source) && {SEARCH_SOURCE.includes(props.source) &&
deploymentType === 'modelList' && ( deploymentType === 'modelList' && (
<> <>
<ColWrapper> <ColWrapper>
<ColumnWrapper> <SearchModel
<SearchModel hasLinuxWorker={hasLinuxWorker}
hasLinuxWorker={hasLinuxWorker} modelSource={props.source}
modelSource={props.source} onSelectModel={handleOnSelectModel}
onSelectModel={handleOnSelectModel} onSelectModelAfterEvaluate={handleOnSelectModelAfterEvaluate}
onSelectModelAfterEvaluate={ clusterId={
handleOnSelectModelAfterEvaluate form.current?.getFieldValue?.('cluster_id') ||
} initClusterId()
clusterId={ }
form.current?.getFieldValue?.('cluster_id') || displayEvaluateStatus={displayEvaluateStatus}
initClusterId() gpuOptions={[]}
} ></SearchModel>
displayEvaluateStatus={displayEvaluateStatus}
gpuOptions={[]}
></SearchModel>
</ColumnWrapper>
<Separator></Separator> <Separator></Separator>
</ColWrapper> </ColWrapper>
<ColWrapper> <ColWrapper>
<ColumnWrapper> <ColumnWrapper styles={{ container: { paddingTop: 0 } }}>
<ModelCard <ModelCard
selectedModel={selectedModel} selectedModel={selectedModel}
onCollapse={setCollapsed} onCollapse={setCollapsed}
@@ -545,7 +546,7 @@ const AddModal: FC<AddModalProps> = (props) => {
</> </>
</ColumnWrapper> </ColumnWrapper>
</FormWrapper> </FormWrapper>
</div> </Container>
</GSDrawer> </GSDrawer>
); );
}; };
+15 -13
View File
@@ -1,6 +1,7 @@
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 ColumnWrapper from '@/pages/_components/column-wrapper';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Pagination } from 'antd'; import { Pagination } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
@@ -521,11 +522,11 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
onChange={handleSearchInputChange} onChange={handleSearchInputChange}
modelSource={modelSource} modelSource={modelSource}
></SearchInput> ></SearchInput>
<div className="gguf-tips"> {/* <div className="gguf-tips">
<span> <span>
{intl.formatMessage({ id: 'models.form.search.gguftips' })} {intl.formatMessage({ id: 'models.form.search.gguftips' })}
</span> </span>
</div> </div> */}
<div className={SearchStyle.filter}> <div className={SearchStyle.filter}>
<span className="flex-center gap-8"> <span className="flex-center gap-8">
<BaseSelect <BaseSelect
@@ -582,18 +583,19 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
}, []); }, []);
return ( return (
<div style={{ flex: 1 }}> <div style={{ width: '100%' }}>
<div className={SearchStyle['search-bar']}>{renderHFSearch()}</div> <div className={SearchStyle['search-bar']}>{renderHFSearch()}</div>
<ColumnWrapper maxHeight={'calc(100vh - 210px)'}>
<SearchResult <SearchResult
loading={dataSource.loading} loading={dataSource.loading}
resultList={dataSource.dataList} resultList={dataSource.dataList}
networkError={dataSource.networkError} networkError={dataSource.networkError}
current={current} current={current}
source={modelSource} source={modelSource}
isEvaluating={isEvaluating} isEvaluating={isEvaluating}
onSelect={handleSelectModelManually} onSelect={handleSelectModelManually}
></SearchResult> ></SearchResult>
</ColumnWrapper>
</div> </div>
); );
}; };
@@ -1,5 +1,4 @@
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import SimpleOverlay from '@/components/simple-overlay';
import { SearchOutlined } from '@ant-design/icons'; import { SearchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Empty, Spin } from 'antd'; import { Button, Empty, Spin } from 'antd';
@@ -121,7 +120,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
}, [networkError, source, intl]); }, [networkError, source, intl]);
return ( return (
<SimpleOverlay style={{ height: 'calc(100vh - 224px)' }}> <>
<div style={{ ...props.style }} className="search-result-wrap"> <div style={{ ...props.style }} className="search-result-wrap">
<Spin spinning={props.loading}> <Spin spinning={props.loading}>
<div style={{ minHeight: 200 }}> <div style={{ minHeight: 200 }}>
@@ -167,7 +166,7 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
</div> </div>
</Spin> </Spin>
</div> </div>
</SimpleOverlay> </>
); );
}; };
+1 -1
View File
@@ -7,7 +7,7 @@ interface FormContextProps {
formKey: DeployFormKey; formKey: DeployFormKey;
source: string; source: string;
pageAction: PageActionType; pageAction: PageActionType;
gpuOptions?: any[]; gpuOptions: any[];
backendOptions: BackendOption[]; backendOptions: BackendOption[];
onValuesChange?: (changedValues: any, allValues: any) => void; onValuesChange?: (changedValues: any, allValues: any) => void;
onBackendChange: (backend: string, option: any) => void; onBackendChange: (backend: string, option: any) => void;
+211
View File
@@ -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;
@@ -14,9 +14,14 @@ import useCheckBackend from '../hooks/use-check-backend';
const LocalPathForm: React.FC = () => { const LocalPathForm: React.FC = () => {
const { checkOnlyAscendNPU } = useCheckBackend(); const { checkOnlyAscendNPU } = useCheckBackend();
const form = Form.useFormInstance(); const form = Form.useFormInstance();
const formCtx = useFormContext();
const source = Form.useWatch('source', form); const source = Form.useWatch('source', form);
const { formKey, gpuOptions, onValuesChange, onBackendChange } = formCtx; const {
formKey,
gpuOptions,
backendOptions,
onValuesChange,
onBackendChange
} = useFormContext();
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') || '');
@@ -58,7 +63,8 @@ const LocalPathForm: React.FC = () => {
}); });
if (oldBackend !== backend) { if (oldBackend !== backend) {
onBackendChange?.(backend); const option = backendOptions.find((item) => item.value === backend);
onBackendChange?.(backend, option);
} else { } else {
onValuesChange?.({ local_path: value }, form.getFieldsValue()); onValuesChange?.({ local_path: value }, form.getFieldsValue());
} }
@@ -5,10 +5,10 @@ import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
import React from 'react'; import React from 'react';
import GPUCard from '../components/gpu-card';
import { scheduleList, ScheduleValueMap } from '../config'; import { scheduleList, ScheduleValueMap } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { useCatalogFormContext, useFormContext } from '../config/form-context'; import { useCatalogFormContext, useFormContext } from '../config/form-context';
import GPUCard from './gpu-card';
const scheduleTypeTips = [ const scheduleTypeTips = [
{ {
-5
View File
@@ -26,8 +26,3 @@
justify-content: flex-end; justify-content: flex-end;
} }
} }
.card-wrapper {
padding: 16px 24px;
padding-top: 0;
}
+2 -3
View File
@@ -1,7 +1,6 @@
@padding: 24px; @padding: 24px;
.search-result-wrap { .search-result-wrap {
padding: 16px @padding;
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base); border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
.ant-spin-container.ant-spin-blur { .ant-spin-container.ant-spin-blur {
@@ -21,8 +20,6 @@
} }
.search-bar { .search-bar {
left: 0;
right: 0;
padding-inline: @padding; padding-inline: @padding;
background: var(--ant-color-bg-elevated); background: var(--ant-color-bg-elevated);
padding-bottom: 10px; padding-bottom: 10px;
@@ -32,6 +29,8 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-top: 10px; margin-top: 10px;
row-gap: 10px;
flex-wrap: wrap;
color: var(--ant-color-text-tertiary); color: var(--ant-color-text-tertiary);
:global { :global {