| @@ -118,3 +118,14 @@ export const autoMLResamplingStrategyOptions = [ | |||||
| { label: 'holdout', value: AutoMLResamplingStrategy.Holdout }, | { label: 'holdout', value: AutoMLResamplingStrategy.Holdout }, | ||||
| { label: 'crossValid', value: AutoMLResamplingStrategy.CrossValid }, | { label: 'crossValid', value: AutoMLResamplingStrategy.CrossValid }, | ||||
| ]; | ]; | ||||
| // 超参数自动寻优优化方向 | |||||
| export enum hyperParameterOptimizedMode { | |||||
| Min = 'min', | |||||
| Max = 'max', | |||||
| } | |||||
| export const hyperParameterOptimizedModeOptions = [ | |||||
| { label: '越大越好', value: hyperParameterOptimizedMode.Max }, | |||||
| { label: '越小越好', value: hyperParameterOptimizedMode.Min }, | |||||
| ]; | |||||
| @@ -190,7 +190,7 @@ function CreateAutoML() { | |||||
| <TrialConfig /> | <TrialConfig /> | ||||
| <DatasetConfig /> | <DatasetConfig /> | ||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }}> | |||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}> | |||||
| <Button type="primary" htmlType="submit"> | <Button type="primary" htmlType="submit"> | ||||
| {buttonText} | {buttonText} | ||||
| </Button> | </Button> | ||||
| @@ -3,9 +3,7 @@ | |||||
| * @Date: 2024-04-16 13:58:08 | * @Date: 2024-04-16 13:58:08 | ||||
| * @Description: 自主机器学习详情 | * @Description: 自主机器学习详情 | ||||
| */ | */ | ||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { CommonTabKeys } from '@/enums'; | |||||
| import { getAutoMLInfoReq } from '@/services/autoML'; | import { getAutoMLInfoReq } from '@/services/autoML'; | ||||
| import { safeInvoke } from '@/utils/functional'; | import { safeInvoke } from '@/utils/functional'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| @@ -16,24 +14,10 @@ import { AutoMLData } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function AutoMLInfo() { | function AutoMLInfo() { | ||||
| const [activeTab, setActiveTab] = useState<string>(CommonTabKeys.Public); | |||||
| const params = useParams(); | const params = useParams(); | ||||
| const autoMLId = safeInvoke(Number)(params.id); | const autoMLId = safeInvoke(Number)(params.id); | ||||
| const [autoMLInfo, setAutoMLInfo] = useState<AutoMLData | undefined>(undefined); | const [autoMLInfo, setAutoMLInfo] = useState<AutoMLData | undefined>(undefined); | ||||
| const tabItems = [ | |||||
| { | |||||
| key: CommonTabKeys.Public, | |||||
| label: '基本信息', | |||||
| icon: <KFIcon type="icon-jibenxinxi" />, | |||||
| }, | |||||
| { | |||||
| key: CommonTabKeys.Private, | |||||
| label: 'Trial列表', | |||||
| icon: <KFIcon type="icon-Trialliebiao" />, | |||||
| }, | |||||
| ]; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (autoMLId) { | if (autoMLId) { | ||||
| getAutoMLInfo(); | getAutoMLInfo(); | ||||
| @@ -4,6 +4,7 @@ import { experimentStatusInfo } from '@/pages/Experiment/status'; | |||||
| import { type NodeStatus } from '@/types'; | import { type NodeStatus } from '@/types'; | ||||
| import { parseJsonText } from '@/utils'; | import { parseJsonText } from '@/utils'; | ||||
| import { elapsedTime } from '@/utils/date'; | import { elapsedTime } from '@/utils/date'; | ||||
| import { formatDataset } from '@/utils/format'; | |||||
| import { Flex } from 'antd'; | import { Flex } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| @@ -15,14 +16,6 @@ import ConfigInfo, { | |||||
| } from '../ConfigInfo'; | } from '../ConfigInfo'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| // 格式化数据集 | |||||
| const formatDataset = (dataset: { name: string; version: string }) => { | |||||
| if (!dataset || !dataset.name || !dataset.version) { | |||||
| return '--'; | |||||
| } | |||||
| return `${dataset.name}:${dataset.version}`; | |||||
| }; | |||||
| // 格式化优化方向 | // 格式化优化方向 | ||||
| const formatOptimizeMode = (value: boolean) => { | const formatOptimizeMode = (value: boolean) => { | ||||
| return value ? '越大越好' : '越小越好'; | return value ? '越大越好' : '越小越好'; | ||||
| @@ -11,13 +11,15 @@ type ConfigInfoProps = { | |||||
| labelWidth: number; | labelWidth: number; | ||||
| className?: string; | className?: string; | ||||
| style?: React.CSSProperties; | style?: React.CSSProperties; | ||||
| children?: React.ReactNode; | |||||
| }; | }; | ||||
| function ConfigInfo({ title, data, labelWidth, className, style }: ConfigInfoProps) { | |||||
| function ConfigInfo({ title, data, labelWidth, className, style, children }: ConfigInfoProps) { | |||||
| return ( | return ( | ||||
| <InfoGroup title={title} className={classNames(styles['config-info'], className)} style={style}> | <InfoGroup title={title} className={classNames(styles['config-info'], className)} style={style}> | ||||
| <div className={styles['config-info__content']}> | <div className={styles['config-info__content']}> | ||||
| <BasicInfo datas={data} labelWidth={labelWidth} /> | <BasicInfo datas={data} labelWidth={labelWidth} /> | ||||
| {children} | |||||
| </div> | </div> | ||||
| </InfoGroup> | </InfoGroup> | ||||
| ); | ); | ||||
| @@ -400,6 +400,7 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| expandable={{ | expandable={{ | ||||
| expandedRowRender: (record) => ( | expandedRowRender: (record) => ( | ||||
| <ExperimentInstance | <ExperimentInstance | ||||
| type={type} | |||||
| experimentInsList={experimentInsList} | experimentInsList={experimentInsList} | ||||
| experimentInsTotal={experimentInsTotal} | experimentInsTotal={experimentInsTotal} | ||||
| onClickInstance={(item) => gotoInstanceInfo(record, item)} | onClickInstance={(item) => gotoInstanceInfo(record, item)} | ||||
| @@ -1,17 +1,8 @@ | |||||
| import BasicTableInfo, { BasicInfoData } from '@/components/BasicTableInfo'; | import BasicTableInfo, { BasicInfoData } from '@/components/BasicTableInfo'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo'; | |||||
| import { | |||||
| DataSource, | |||||
| DatasetData, | |||||
| ModelData, | |||||
| ProjectDependency, | |||||
| ResourceType, | |||||
| TrainTask, | |||||
| resourceConfig, | |||||
| } from '@/pages/Dataset/config'; | |||||
| import { DatasetData, ModelData, ResourceType, resourceConfig } from '@/pages/Dataset/config'; | |||||
| import ModelMetrics from '@/pages/Model/components/ModelMetrics'; | import ModelMetrics from '@/pages/Model/components/ModelMetrics'; | ||||
| import { getGitUrl } from '@/utils'; | |||||
| import { formatCodeConfig, formatDatasets, formatSource, formatTrainTask } from '@/utils/format'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -24,55 +15,6 @@ type ResourceIntroProps = { | |||||
| version?: string; | version?: string; | ||||
| }; | }; | ||||
| export const formatDataset = (datasets?: DatasetData[]) => { | |||||
| if (!datasets || datasets.length === 0) { | |||||
| return undefined; | |||||
| } | |||||
| return datasets.map((item) => ({ | |||||
| value: item.name, | |||||
| url: `${origin}/dataset/dataset/info/${item.id}?tab=${ResourceInfoTabKeys.Version}&version=${item.version}&name=${item.name}&owner=${item.owner}&identifier=${item.identifier}`, | |||||
| })); | |||||
| }; | |||||
| export const getProjectUrl = (project?: ProjectDependency) => { | |||||
| if (!project || !project.url || !project.branch) { | |||||
| return undefined; | |||||
| } | |||||
| const { url, branch } = project; | |||||
| return getGitUrl(url, branch); | |||||
| }; | |||||
| export const formatProject = (project?: ProjectDependency) => { | |||||
| if (!project) { | |||||
| return undefined; | |||||
| } | |||||
| return { | |||||
| value: project.name, | |||||
| url: getProjectUrl(project), | |||||
| }; | |||||
| }; | |||||
| export const formatTrainTask = (task?: TrainTask) => { | |||||
| if (!task) { | |||||
| return undefined; | |||||
| } | |||||
| return { | |||||
| value: task.name, | |||||
| url: `${origin}/pipeline/experiment/instance/${task.workflow_id}/${task.ins_id}`, | |||||
| }; | |||||
| }; | |||||
| export const formatSource = (source?: string) => { | |||||
| if (source === DataSource.Create) { | |||||
| return '用户上传'; | |||||
| } else if (source === DataSource.HandExport) { | |||||
| return '手动导入'; | |||||
| } else if (source === DataSource.AtuoExport) { | |||||
| return '实验自动导入'; | |||||
| } | |||||
| return source; | |||||
| }; | |||||
| const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [ | const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [ | ||||
| { | { | ||||
| label: '数据集名称', | label: '数据集名称', | ||||
| @@ -109,7 +51,7 @@ const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [ | |||||
| { | { | ||||
| label: '处理代码', | label: '处理代码', | ||||
| value: data.processing_code, | value: data.processing_code, | ||||
| format: formatProject, | |||||
| format: formatCodeConfig, | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -153,19 +95,19 @@ const getModelDatas = (data: ModelData): BasicInfoData[] => [ | |||||
| { | { | ||||
| label: '训练代码', | label: '训练代码', | ||||
| value: data.project_depency, | value: data.project_depency, | ||||
| format: formatProject, | |||||
| format: formatCodeConfig, | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| { | { | ||||
| label: '训练数据集', | label: '训练数据集', | ||||
| value: data.train_datasets, | value: data.train_datasets, | ||||
| format: formatDataset, | |||||
| format: formatDatasets, | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| { | { | ||||
| label: '测试数据集', | label: '测试数据集', | ||||
| value: data.test_datasets, | value: data.test_datasets, | ||||
| format: formatDataset, | |||||
| format: formatDatasets, | |||||
| ellipsis: true, | ellipsis: true, | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -8,11 +8,11 @@ import { | |||||
| resourceConfig, | resourceConfig, | ||||
| } from '@/pages/Dataset/config'; | } from '@/pages/Dataset/config'; | ||||
| import { isEmpty } from '@/utils'; | import { isEmpty } from '@/utils'; | ||||
| import { formatSource } from '@/utils/format'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { Typography, type ModalProps } from 'antd'; | import { Typography, type ModalProps } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useEffect, useMemo, useState } from 'react'; | import { useEffect, useMemo, useState } from 'react'; | ||||
| import { formatSource } from '../ResourceIntro'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| type CompareData = { | type CompareData = { | ||||
| @@ -47,10 +47,10 @@ const formatProject = (project?: ProjectDependency) => { | |||||
| if (!project) { | if (!project) { | ||||
| return undefined; | return undefined; | ||||
| } | } | ||||
| return project.name; | |||||
| return `${project.name}:${project.branch}`; | |||||
| }; | }; | ||||
| export const formatTrainTask = (task?: TrainTask) => { | |||||
| const formatTrainTask = (task?: TrainTask) => { | |||||
| if (!task) { | if (!task) { | ||||
| return undefined; | return undefined; | ||||
| } | } | ||||
| @@ -41,10 +41,9 @@ function CreateHyperparameter() { | |||||
| const name = isCopy ? `${name_str}-copy` : name_str; | const name = isCopy ? `${name_str}-copy` : name_str; | ||||
| if (parameters && Array.isArray(parameters)) { | if (parameters && Array.isArray(parameters)) { | ||||
| parameters.forEach((item) => { | parameters.forEach((item) => { | ||||
| item.range = item.bounds || item.values || item.value; | |||||
| delete item.bounds; | |||||
| delete item.values; | |||||
| delete item.value; | |||||
| const paramName = getReqParamName(item.type); | |||||
| item.range = item[paramName]; | |||||
| item[paramName] = undefined; | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -63,8 +62,6 @@ function CreateHyperparameter() { | |||||
| const createExperiment = async (formData: FormData) => { | const createExperiment = async (formData: FormData) => { | ||||
| // 按后台接口要求,修改参数表单数据结构,将 "value" 参数改为 "bounds"/"values"/"value" | // 按后台接口要求,修改参数表单数据结构,将 "value" 参数改为 "bounds"/"values"/"value" | ||||
| const parameters = formData['parameters']; | const parameters = formData['parameters']; | ||||
| // const points_to_evaluate = formData['points_to_evaluate']; | |||||
| // const runParameters = formData['parameters']; | |||||
| parameters.forEach((item) => { | parameters.forEach((item) => { | ||||
| const paramName = getReqParamName(item.type); | const paramName = getReqParamName(item.type); | ||||
| item[paramName] = item.range; | item[paramName] = item.range; | ||||
| @@ -142,7 +139,7 @@ function CreateHyperparameter() { | |||||
| <BasicConfig /> | <BasicConfig /> | ||||
| <ExecuteConfig /> | <ExecuteConfig /> | ||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }}> | |||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}> | |||||
| <Button type="primary" htmlType="submit"> | <Button type="primary" htmlType="submit"> | ||||
| {buttonText} | {buttonText} | ||||
| </Button> | </Button> | ||||
| @@ -3,48 +3,34 @@ | |||||
| * @Date: 2024-04-16 13:58:08 | * @Date: 2024-04-16 13:58:08 | ||||
| * @Description: 自主机器学习详情 | * @Description: 自主机器学习详情 | ||||
| */ | */ | ||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { CommonTabKeys } from '@/enums'; | |||||
| import { getAutoMLInfoReq } from '@/services/autoML'; | |||||
| import { getRayInfoReq } from '@/services/hyperParameter'; | |||||
| import { safeInvoke } from '@/utils/functional'; | import { safeInvoke } from '@/utils/functional'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useParams } from '@umijs/max'; | import { useParams } from '@umijs/max'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import AutoMLBasic from '../components/AutoMLBasic'; | |||||
| import HyperParameterBasic from '../components/HyperParameterBasic'; | |||||
| import { HyperparameterData } from '../types'; | import { HyperparameterData } from '../types'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function AutoMLInfo() { | |||||
| const [activeTab, setActiveTab] = useState<string>(CommonTabKeys.Public); | |||||
| function HyperparameterInfo() { | |||||
| const params = useParams(); | const params = useParams(); | ||||
| const autoMLId = safeInvoke(Number)(params.id); | |||||
| const [autoMLInfo, setAutoMLInfo] = useState<HyperparameterData | undefined>(undefined); | |||||
| const tabItems = [ | |||||
| { | |||||
| key: CommonTabKeys.Public, | |||||
| label: '基本信息', | |||||
| icon: <KFIcon type="icon-jibenxinxi" />, | |||||
| }, | |||||
| { | |||||
| key: CommonTabKeys.Private, | |||||
| label: 'Trial列表', | |||||
| icon: <KFIcon type="icon-Trialliebiao" />, | |||||
| }, | |||||
| ]; | |||||
| const hyperparameterId = safeInvoke(Number)(params.id); | |||||
| const [hyperparameterInfo, setHyperparameterInfo] = useState<HyperparameterData | undefined>( | |||||
| undefined, | |||||
| ); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (autoMLId) { | |||||
| getAutoMLInfo(); | |||||
| if (hyperparameterId) { | |||||
| getHyperparameterInfo(); | |||||
| } | } | ||||
| }, []); | }, []); | ||||
| // 获取自动机器学习详情 | // 获取自动机器学习详情 | ||||
| const getAutoMLInfo = async () => { | |||||
| const [res] = await to(getAutoMLInfoReq({ id: autoMLId })); | |||||
| const getHyperparameterInfo = async () => { | |||||
| const [res] = await to(getRayInfoReq({ id: hyperparameterId })); | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| setAutoMLInfo(res.data); | |||||
| setHyperparameterInfo(res.data); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -52,10 +38,10 @@ function AutoMLInfo() { | |||||
| <div className={styles['auto-ml-info']}> | <div className={styles['auto-ml-info']}> | ||||
| <PageTitle title="实验详情"></PageTitle> | <PageTitle title="实验详情"></PageTitle> | ||||
| <div className={styles['auto-ml-info__content']}> | <div className={styles['auto-ml-info__content']}> | ||||
| <AutoMLBasic info={autoMLInfo} /> | |||||
| <HyperParameterBasic info={hyperparameterInfo} /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| export default AutoMLInfo; | |||||
| export default HyperparameterInfo; | |||||
| @@ -9,9 +9,9 @@ import { to } from '@/utils/promise'; | |||||
| import { useParams } from '@umijs/max'; | import { useParams } from '@umijs/max'; | ||||
| import { Tabs } from 'antd'; | import { Tabs } from 'antd'; | ||||
| import { useEffect, useRef, useState } from 'react'; | import { useEffect, useRef, useState } from 'react'; | ||||
| import AutoMLBasic from '../components/AutoMLBasic'; | |||||
| import ExperimentHistory from '../components/ExperimentHistory'; | import ExperimentHistory from '../components/ExperimentHistory'; | ||||
| import ExperimentResult from '../components/ExperimentResult'; | import ExperimentResult from '../components/ExperimentResult'; | ||||
| import HyperParameterBasic from '../components/HyperParameterBasic'; | |||||
| import { AutoMLInstanceData, HyperparameterData } from '../types'; | import { AutoMLInstanceData, HyperparameterData } from '../types'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -140,7 +140,7 @@ function AutoMLInstance() { | |||||
| label: '基本信息', | label: '基本信息', | ||||
| icon: <KFIcon type="icon-jibenxinxi" />, | icon: <KFIcon type="icon-jibenxinxi" />, | ||||
| children: ( | children: ( | ||||
| <AutoMLBasic | |||||
| <HyperParameterBasic | |||||
| className={styles['auto-ml-instance__basic']} | className={styles['auto-ml-instance__basic']} | ||||
| info={autoMLInfo} | info={autoMLInfo} | ||||
| runStatus={instanceInfo?.nodeStatus} | runStatus={instanceInfo?.nodeStatus} | ||||
| @@ -1,308 +0,0 @@ | |||||
| import { AutoMLTaskType, autoMLEnsembleClassOptions, autoMLTaskTypeOptions } from '@/enums'; | |||||
| import { AutoMLData } from '@/pages/AutoML/types'; | |||||
| import { experimentStatusInfo } from '@/pages/Experiment/status'; | |||||
| import { type NodeStatus } from '@/types'; | |||||
| import { parseJsonText } from '@/utils'; | |||||
| import { elapsedTime } from '@/utils/date'; | |||||
| import { Flex } from 'antd'; | |||||
| import classNames from 'classnames'; | |||||
| import { useMemo } from 'react'; | |||||
| import ConfigInfo, { | |||||
| formatBoolean, | |||||
| formatDate, | |||||
| formatEnum, | |||||
| type BasicInfoData, | |||||
| } from '../ConfigInfo'; | |||||
| import styles from './index.less'; | |||||
| // 格式化数据集 | |||||
| const formatDataset = (dataset: { name: string; version: string }) => { | |||||
| if (!dataset || !dataset.name || !dataset.version) { | |||||
| return '--'; | |||||
| } | |||||
| return `${dataset.name}:${dataset.version}`; | |||||
| }; | |||||
| // 格式化优化方向 | |||||
| const formatOptimizeMode = (value: boolean) => { | |||||
| return value ? '越大越好' : '越小越好'; | |||||
| }; | |||||
| const formatMetricsWeight = (value: string) => { | |||||
| if (!value) { | |||||
| return '--'; | |||||
| } | |||||
| const json = parseJsonText(value); | |||||
| if (!json) { | |||||
| return '--'; | |||||
| } | |||||
| return Object.entries(json) | |||||
| .map(([key, value]) => `${key}:${value}`) | |||||
| .join('\n'); | |||||
| }; | |||||
| type AutoMLBasicProps = { | |||||
| info?: AutoMLData; | |||||
| className?: string; | |||||
| isInstance?: boolean; | |||||
| runStatus?: NodeStatus; | |||||
| }; | |||||
| function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) { | |||||
| const basicDatas: BasicInfoData[] = useMemo(() => { | |||||
| if (!info) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '实验名称', | |||||
| value: info.ml_name, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '实验描述', | |||||
| value: info.ml_description, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '创建人', | |||||
| value: info.create_by, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '创建时间', | |||||
| value: info.create_time, | |||||
| ellipsis: true, | |||||
| format: formatDate, | |||||
| }, | |||||
| { | |||||
| label: '更新时间', | |||||
| value: info.update_time, | |||||
| ellipsis: true, | |||||
| format: formatDate, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| const configDatas: BasicInfoData[] = useMemo(() => { | |||||
| if (!info) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '任务类型', | |||||
| value: info.task_type, | |||||
| ellipsis: true, | |||||
| format: formatEnum(autoMLTaskTypeOptions), | |||||
| }, | |||||
| { | |||||
| label: '特征预处理算法', | |||||
| value: info.include_feature_preprocessor, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '排除的特征预处理算法', | |||||
| value: info.exclude_feature_preprocessor, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '回归算法' : '分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.include_regressor | |||||
| : info.include_classifier, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: info.task_type === AutoMLTaskType.Regression ? '排除的回归算法' : '排除的分类算法', | |||||
| value: | |||||
| info.task_type === AutoMLTaskType.Regression | |||||
| ? info.exclude_regressor | |||||
| : info.exclude_classifier, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '集成方式', | |||||
| value: info.ensemble_class, | |||||
| ellipsis: true, | |||||
| format: formatEnum(autoMLEnsembleClassOptions), | |||||
| }, | |||||
| { | |||||
| label: '集成模型数量', | |||||
| value: info.ensemble_size, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '集成最佳模型数量', | |||||
| value: info.ensemble_nbest, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '最大数量', | |||||
| value: info.max_models_on_disc, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '内存限制(MB)', | |||||
| value: info.memory_limit, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '单次时间限制(秒)', | |||||
| value: info.per_run_time_limit, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '搜索时间限制(秒)', | |||||
| value: info.time_left_for_this_task, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '重采样策略', | |||||
| value: info.resampling_strategy, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '交叉验证折数', | |||||
| value: info.folds, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '是否打乱', | |||||
| value: info.shuffle, | |||||
| ellipsis: true, | |||||
| format: formatBoolean, | |||||
| }, | |||||
| { | |||||
| label: '训练集比率', | |||||
| value: info.train_size, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '测试集比率', | |||||
| value: info.test_size, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '计算指标', | |||||
| value: info.scoring_functions, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '随机种子', | |||||
| value: info.seed, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '数据集', | |||||
| value: info.dataset, | |||||
| ellipsis: true, | |||||
| format: formatDataset, | |||||
| }, | |||||
| { | |||||
| label: '预测目标列', | |||||
| value: info.target_columns, | |||||
| ellipsis: true, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| const metricsData = useMemo(() => { | |||||
| if (!info) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '指标名称', | |||||
| value: info.metric_name, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '优化方向', | |||||
| value: info.greater_is_better, | |||||
| ellipsis: true, | |||||
| format: formatOptimizeMode, | |||||
| }, | |||||
| { | |||||
| label: '指标权重', | |||||
| value: info.metrics, | |||||
| ellipsis: true, | |||||
| format: formatMetricsWeight, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| const instanceDatas = useMemo(() => { | |||||
| if (!runStatus) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '启动时间', | |||||
| value: formatDate(runStatus.startedAt), | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '执行时长', | |||||
| value: elapsedTime(runStatus.startedAt, runStatus.finishedAt), | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '状态', | |||||
| value: ( | |||||
| <Flex align="center"> | |||||
| <img | |||||
| style={{ width: '17px', marginRight: '7px' }} | |||||
| src={experimentStatusInfo[runStatus.phase]?.icon} | |||||
| draggable={false} | |||||
| alt="" | |||||
| /> | |||||
| <div | |||||
| style={{ | |||||
| color: experimentStatusInfo[runStatus?.phase]?.color, | |||||
| fontSize: '15px', | |||||
| lineHeight: 1.6, | |||||
| }} | |||||
| > | |||||
| {experimentStatusInfo[runStatus?.phase]?.label} | |||||
| </div> | |||||
| </Flex> | |||||
| ), | |||||
| ellipsis: true, | |||||
| }, | |||||
| ]; | |||||
| }, [runStatus]); | |||||
| return ( | |||||
| <div className={classNames(styles['auto-ml-basic'], className)}> | |||||
| {isInstance && runStatus && ( | |||||
| <ConfigInfo | |||||
| title="运行信息" | |||||
| data={instanceDatas} | |||||
| labelWidth={70} | |||||
| style={{ marginBottom: '20px' }} | |||||
| /> | |||||
| )} | |||||
| {!isInstance && ( | |||||
| <ConfigInfo | |||||
| title="基本信息" | |||||
| data={basicDatas} | |||||
| labelWidth={70} | |||||
| style={{ marginBottom: '20px' }} | |||||
| /> | |||||
| )} | |||||
| <ConfigInfo | |||||
| title="配置信息" | |||||
| data={configDatas} | |||||
| labelWidth={150} | |||||
| style={{ marginBottom: '20px' }} | |||||
| /> | |||||
| <ConfigInfo title="优化指标" data={metricsData} labelWidth={70} /> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default AutoMLBasic; | |||||
| @@ -1,20 +0,0 @@ | |||||
| .config-info { | |||||
| :global { | |||||
| .kf-basic-info { | |||||
| width: 100%; | |||||
| &__item { | |||||
| width: calc((100% - 80px) / 3); | |||||
| &__label { | |||||
| font-size: @font-size; | |||||
| text-align: left; | |||||
| text-align-last: left; | |||||
| } | |||||
| &__value { | |||||
| min-width: 0; | |||||
| font-size: @font-size; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,26 +0,0 @@ | |||||
| import BasicInfo, { type BasicInfoData } from '@/components/BasicInfo'; | |||||
| import InfoGroup from '@/components/InfoGroup'; | |||||
| import classNames from 'classnames'; | |||||
| import styles from './index.less'; | |||||
| export * from '@/components/BasicInfo/format'; | |||||
| export type { BasicInfoData }; | |||||
| type ConfigInfoProps = { | |||||
| title: string; | |||||
| data: BasicInfoData[]; | |||||
| labelWidth: number; | |||||
| className?: string; | |||||
| style?: React.CSSProperties; | |||||
| }; | |||||
| function ConfigInfo({ title, data, labelWidth, className, style }: ConfigInfoProps) { | |||||
| return ( | |||||
| <InfoGroup title={title} className={classNames(styles['config-info'], className)} style={style}> | |||||
| <div className={styles['config-info__content']}> | |||||
| <BasicInfo datas={data} labelWidth={labelWidth} /> | |||||
| </div> | |||||
| </InfoGroup> | |||||
| ); | |||||
| } | |||||
| export default ConfigInfo; | |||||
| @@ -5,6 +5,7 @@ import ResourceSelect, { | |||||
| requiredValidator, | requiredValidator, | ||||
| } from '@/components/ResourceSelect'; | } from '@/components/ResourceSelect'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { hyperParameterOptimizedModeOptions } from '@/enums'; | |||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; | import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; | ||||
| import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd'; | import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd'; | ||||
| @@ -456,10 +457,7 @@ function ExecuteConfig() { | |||||
| name="mode" | name="mode" | ||||
| rules={[{ required: true, message: '请选择优化方向' }]} | rules={[{ required: true, message: '请选择优化方向' }]} | ||||
| > | > | ||||
| <Radio.Group> | |||||
| <Radio value={'max'}>越大越好</Radio> | |||||
| <Radio value={'min'}>越小越好</Radio> | |||||
| </Radio.Group> | |||||
| <Radio.Group options={hyperParameterOptimizedModeOptions}></Radio.Group> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -467,16 +465,16 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="CPU 数" | |||||
| label="CPU 数量" | |||||
| name="cpu" | name="cpu" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入 CPU 数', | |||||
| message: '请输入 CPU 数量', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <InputNumber placeholder="请输入 CPU 数" min={0} precision={0} /> | |||||
| <InputNumber placeholder="请输入 CPU 数量" min={0} precision={0} /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -484,16 +482,16 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="GPU 数" | |||||
| label="GPU 数量" | |||||
| name="gpu" | name="gpu" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入 GPU 数', | |||||
| message: '请输入 GPU 数量', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <InputNumber placeholder="请输入 GPU 数" min={0} precision={0} /> | |||||
| <InputNumber placeholder="请输入 GPU 数量" min={0} precision={0} /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -1,5 +1,8 @@ | |||||
| .parameter-range { | .parameter-range { | ||||
| :global { | :global { | ||||
| .ant-popover-inner { | |||||
| padding: 20px 20px 12px; | |||||
| } | |||||
| .ant-popconfirm-description { | .ant-popconfirm-description { | ||||
| padding-top: 20px; | padding-top: 20px; | ||||
| } | } | ||||
| @@ -22,15 +25,6 @@ | |||||
| border-radius: 8px; | border-radius: 8px; | ||||
| cursor: pointer; | cursor: pointer; | ||||
| &:hover { | |||||
| border-color: #4086ff; | |||||
| } | |||||
| &--disabled { | |||||
| background-color: rgba(0, 0, 0, 0.04); | |||||
| cursor: not-allowed; | |||||
| } | |||||
| &__text { | &__text { | ||||
| flex: 1; | flex: 1; | ||||
| margin-right: 10px; | margin-right: 10px; | ||||
| @@ -40,8 +34,22 @@ | |||||
| flex: none; | flex: none; | ||||
| } | } | ||||
| &--disabled &__icon { | |||||
| color: @text-color-tertiary; | |||||
| &:hover { | |||||
| border-color: #4086ff; | |||||
| } | |||||
| &:hover &__icon { | |||||
| color: #4086ff; | |||||
| } | |||||
| &&--disabled { | |||||
| background-color: rgba(0, 0, 0, 0.04); | |||||
| border-color: rgba(0, 0, 0, 0.04) !important; | |||||
| cursor: not-allowed; | |||||
| } | |||||
| &&--disabled &__icon { | |||||
| color: #aaaaaa !important; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -92,12 +92,13 @@ | |||||
| .run-parameter { | .run-parameter { | ||||
| width: calc(41.66% + 126px); | width: calc(41.66% + 126px); | ||||
| margin-bottom: 20px; | margin-bottom: 20px; | ||||
| border-radius: 8px; | |||||
| &__body { | &__body { | ||||
| flex: 1; | flex: 1; | ||||
| margin-right: 10px; | margin-right: 10px; | ||||
| padding: 20px 20px 0; | padding: 20px 20px 0; | ||||
| border: 1px dashed @border-color-base; | |||||
| border: 1px dashed #dddddd; | |||||
| border-radius: 8px; | |||||
| } | } | ||||
| &__operation { | &__operation { | ||||
| display: flex; | display: flex; | ||||
| @@ -1,4 +1,4 @@ | |||||
| .auto-ml-basic { | |||||
| .hyper-parameter-basic { | |||||
| height: 100%; | height: 100%; | ||||
| padding: 20px @content-padding; | padding: 20px @content-padding; | ||||
| overflow-y: auto; | overflow-y: auto; | ||||
| @@ -0,0 +1,207 @@ | |||||
| import { hyperParameterOptimizedMode } from '@/enums'; | |||||
| import ConfigInfo, { formatDate, type BasicInfoData } from '@/pages/AutoML/components/ConfigInfo'; | |||||
| import { experimentStatusInfo } from '@/pages/Experiment/status'; | |||||
| import { HyperparameterData } from '@/pages/HyperParameter/types'; | |||||
| import { type NodeStatus } from '@/types'; | |||||
| import { elapsedTime } from '@/utils/date'; | |||||
| import { formatDataset, formatSelectCodeConfig } from '@/utils/format'; | |||||
| import { Flex } from 'antd'; | |||||
| import classNames from 'classnames'; | |||||
| import { useMemo } from 'react'; | |||||
| import ParameterInfo from '../ParameterInfo'; | |||||
| import styles from './index.less'; | |||||
| // 格式化优化方向 | |||||
| const formatOptimizeMode = (value: string) => { | |||||
| return value === hyperParameterOptimizedMode.Max ? '越大越好' : '越小越好'; | |||||
| }; | |||||
| type HyperParameterBasicProps = { | |||||
| info?: HyperparameterData; | |||||
| className?: string; | |||||
| isInstance?: boolean; | |||||
| runStatus?: NodeStatus; | |||||
| }; | |||||
| function HyperParameterBasic({ | |||||
| info, | |||||
| className, | |||||
| runStatus, | |||||
| isInstance = false, | |||||
| }: HyperParameterBasicProps) { | |||||
| const basicDatas: BasicInfoData[] = useMemo(() => { | |||||
| if (!info) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '实验名称', | |||||
| value: info.name, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '实验描述', | |||||
| value: info.description, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '创建人', | |||||
| value: info.create_by, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '创建时间', | |||||
| value: info.create_time, | |||||
| ellipsis: true, | |||||
| format: formatDate, | |||||
| }, | |||||
| { | |||||
| label: '更新时间', | |||||
| value: info.update_time, | |||||
| ellipsis: true, | |||||
| format: formatDate, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| const configDatas: BasicInfoData[] = useMemo(() => { | |||||
| if (!info) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '代码', | |||||
| value: info.code, | |||||
| ellipsis: true, | |||||
| format: formatSelectCodeConfig, | |||||
| }, | |||||
| { | |||||
| label: '主函数代码文件', | |||||
| value: info.main_py, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '数据集', | |||||
| value: info.dataset, | |||||
| ellipsis: true, | |||||
| format: formatDataset, | |||||
| }, | |||||
| { | |||||
| label: '数据集挂载路径', | |||||
| value: info.dataset_path, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '总实验次数', | |||||
| value: info.num_samples, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '搜索算法', | |||||
| value: info.search_alg, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '调度算法', | |||||
| value: info.scheduler, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '优化方向', | |||||
| value: info.mode, | |||||
| ellipsis: true, | |||||
| format: formatOptimizeMode, | |||||
| }, | |||||
| { | |||||
| label: '指标', | |||||
| value: info.metric, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: 'CPU 数量', | |||||
| value: info.cpu, | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: 'GPU 数量', | |||||
| value: info.gpu, | |||||
| ellipsis: true, | |||||
| }, | |||||
| ]; | |||||
| }, [info]); | |||||
| const instanceDatas = useMemo(() => { | |||||
| if (!runStatus) { | |||||
| return []; | |||||
| } | |||||
| return [ | |||||
| { | |||||
| label: '启动时间', | |||||
| value: formatDate(runStatus.startedAt), | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '执行时长', | |||||
| value: elapsedTime(runStatus.startedAt, runStatus.finishedAt), | |||||
| ellipsis: true, | |||||
| }, | |||||
| { | |||||
| label: '状态', | |||||
| value: ( | |||||
| <Flex align="center"> | |||||
| <img | |||||
| style={{ width: '17px', marginRight: '7px' }} | |||||
| src={experimentStatusInfo[runStatus.phase]?.icon} | |||||
| draggable={false} | |||||
| alt="" | |||||
| /> | |||||
| <div | |||||
| style={{ | |||||
| color: experimentStatusInfo[runStatus?.phase]?.color, | |||||
| fontSize: '15px', | |||||
| lineHeight: 1.6, | |||||
| }} | |||||
| > | |||||
| {experimentStatusInfo[runStatus?.phase]?.label} | |||||
| </div> | |||||
| </Flex> | |||||
| ), | |||||
| ellipsis: true, | |||||
| }, | |||||
| ]; | |||||
| }, [runStatus]); | |||||
| return ( | |||||
| <div className={classNames(styles['hyper-parameter-basic'], className)}> | |||||
| {isInstance && runStatus && ( | |||||
| <ConfigInfo | |||||
| title="运行信息" | |||||
| data={instanceDatas} | |||||
| labelWidth={70} | |||||
| style={{ marginBottom: '20px' }} | |||||
| /> | |||||
| )} | |||||
| {!isInstance && ( | |||||
| <ConfigInfo | |||||
| title="基本信息" | |||||
| data={basicDatas} | |||||
| labelWidth={70} | |||||
| style={{ marginBottom: '20px' }} | |||||
| /> | |||||
| )} | |||||
| <ConfigInfo | |||||
| title="配置信息" | |||||
| data={configDatas} | |||||
| labelWidth={150} | |||||
| style={{ marginBottom: '20px' }} | |||||
| > | |||||
| {info && <ParameterInfo info={info} />} | |||||
| </ConfigInfo> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default HyperParameterBasic; | |||||
| @@ -0,0 +1,7 @@ | |||||
| .parameter-info { | |||||
| &__title { | |||||
| margin: 20px 0; | |||||
| color: @text-color-secondary; | |||||
| font-size: @font-size; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,108 @@ | |||||
| import { | |||||
| getReqParamName, | |||||
| type FormParameter, | |||||
| } from '@/pages/HyperParameter/components/CreateForm/utils'; | |||||
| import { HyperparameterData } from '@/pages/HyperParameter/types'; | |||||
| import tableCellRender, { TableCellValueType } from '@/utils/table'; | |||||
| import { Table, Tooltip, type TableProps } from 'antd'; | |||||
| import { useMemo } from 'react'; | |||||
| import styles from './index.less'; | |||||
| type ParameterInfoProps = { | |||||
| info: HyperparameterData; | |||||
| }; | |||||
| function ParameterInfo({ info }: ParameterInfoProps) { | |||||
| const parameters = useMemo(() => { | |||||
| if (!info.parameters) { | |||||
| return []; | |||||
| } | |||||
| return info.parameters.map((item) => { | |||||
| const paramName = getReqParamName(item.type); | |||||
| const range = item[paramName]; | |||||
| return { | |||||
| ...item, | |||||
| range, | |||||
| }; | |||||
| }); | |||||
| }, [info]); | |||||
| const runParameters = useMemo(() => { | |||||
| if (!info.points_to_evaluate) { | |||||
| return []; | |||||
| } | |||||
| return info.points_to_evaluate.map((item, index) => ({ | |||||
| ...item, | |||||
| id: index, | |||||
| })); | |||||
| }, [info]); | |||||
| const columns: TableProps<FormParameter>['columns'] = [ | |||||
| { | |||||
| title: '参数名称', | |||||
| dataIndex: 'name', | |||||
| key: 'type', | |||||
| width: '40%', | |||||
| render: tableCellRender(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| }, | |||||
| { | |||||
| title: '参数类型', | |||||
| dataIndex: 'type', | |||||
| key: 'type', | |||||
| width: '20%', | |||||
| render: tableCellRender(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| }, | |||||
| { | |||||
| title: '取值范围', | |||||
| dataIndex: 'range', | |||||
| key: 'range', | |||||
| width: '40%', | |||||
| render: tableCellRender(true, TableCellValueType.Custom, { | |||||
| format: (value) => { | |||||
| return JSON.stringify(value); | |||||
| }, | |||||
| }), | |||||
| ellipsis: { showTitle: false }, | |||||
| }, | |||||
| ]; | |||||
| const runColumns: TableProps<Record<string, any>>['columns'] = | |||||
| runParameters.length > 0 | |||||
| ? Object.keys(runParameters[0]) | |||||
| .filter((key) => key !== 'id') | |||||
| .map((key) => { | |||||
| return { | |||||
| title: ( | |||||
| <Tooltip title={key}> | |||||
| <span>{key}</span> | |||||
| </Tooltip> | |||||
| ), | |||||
| dataIndex: key, | |||||
| key: key, | |||||
| width: 150, | |||||
| render: tableCellRender(true), | |||||
| ellipsis: { showTitle: false }, | |||||
| }; | |||||
| }) | |||||
| : []; | |||||
| return ( | |||||
| <div className={styles['parameter-info']}> | |||||
| <div className={styles['parameter-info__title']}>参数</div> | |||||
| <Table dataSource={parameters} columns={columns} rowKey="name" bordered pagination={false} /> | |||||
| <div className={styles['parameter-info__title']}>手动运行参数</div> | |||||
| <Table | |||||
| dataSource={runParameters} | |||||
| columns={runColumns} | |||||
| rowKey="id" | |||||
| bordered | |||||
| pagination={false} | |||||
| scroll={{ x: '100%' }} | |||||
| /> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default ParameterInfo; | |||||
| @@ -16,7 +16,7 @@ export type FormData = { | |||||
| dataset: ParameterInputObject; // 数据集 | dataset: ParameterInputObject; // 数据集 | ||||
| dataset_path: string; // 数据集路径 | dataset_path: string; // 数据集路径 | ||||
| main_py: string; // 主函数代码文件 | main_py: string; // 主函数代码文件 | ||||
| metrics: string; // 指标 | |||||
| metric: string; // 指标 | |||||
| mode: string; // 优化方向 | mode: string; // 优化方向 | ||||
| search_alg?: string; // 搜索算法 | search_alg?: string; // 搜索算法 | ||||
| scheduler?: string; // 调度算法 | scheduler?: string; // 调度算法 | ||||
| @@ -0,0 +1,87 @@ | |||||
| import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo'; | |||||
| import { DataSource, DatasetData, ProjectDependency, TrainTask } from '@/pages/Dataset/config'; | |||||
| import { getGitUrl } from '@/utils'; | |||||
| // 格式化数据集数组 | |||||
| export const formatDatasets = (datasets?: DatasetData[]) => { | |||||
| if (!datasets || datasets.length === 0) { | |||||
| return undefined; | |||||
| } | |||||
| return datasets.map((item) => ({ | |||||
| value: item.name, | |||||
| url: `${origin}/dataset/dataset/info/${item.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${item.version}&name=${item.name}&owner=${item.owner}&identifier=${item.identifier}`, | |||||
| })); | |||||
| }; | |||||
| // 格式化数据集 | |||||
| export const formatDataset = (dataset?: DatasetData) => { | |||||
| if (!dataset) { | |||||
| return undefined; | |||||
| } | |||||
| return { | |||||
| value: dataset.name, | |||||
| url: `${origin}/dataset/dataset/info/${dataset.id}?tab=${ResourceInfoTabKeys.Introduction}&version=${dataset.version}&name=${dataset.name}&owner=${dataset.owner}&identifier=${dataset.identifier}`, | |||||
| }; | |||||
| }; | |||||
| // 获取代码配置的仓库的 url | |||||
| export const getRepoUrl = (project?: ProjectDependency) => { | |||||
| if (!project) { | |||||
| return undefined; | |||||
| } | |||||
| const { url, branch } = project; | |||||
| return getGitUrl(url, branch); | |||||
| }; | |||||
| // 格式化代码配置 | |||||
| export const formatCodeConfig = (project?: ProjectDependency) => { | |||||
| if (!project) { | |||||
| return undefined; | |||||
| } | |||||
| return { | |||||
| value: project.name, | |||||
| url: getRepoUrl(project), | |||||
| }; | |||||
| }; | |||||
| // 格式化选中的代码配置 | |||||
| export const formatSelectCodeConfig = (value?: { | |||||
| code_path: string; | |||||
| branch: string; | |||||
| showValue: string; | |||||
| }) => { | |||||
| if (!value) { | |||||
| return undefined; | |||||
| } | |||||
| const { showValue, code_path, branch } = value; | |||||
| return { | |||||
| value: showValue, | |||||
| url: getRepoUrl({ | |||||
| url: code_path, | |||||
| branch, | |||||
| } as ProjectDependency), | |||||
| }; | |||||
| }; | |||||
| // 格式化训练任务(实验实例) | |||||
| export const formatTrainTask = (task?: TrainTask) => { | |||||
| if (!task) { | |||||
| return undefined; | |||||
| } | |||||
| return { | |||||
| value: task.name, | |||||
| url: `${origin}/pipeline/experiment/instance/${task.workflow_id}/${task.ins_id}`, | |||||
| }; | |||||
| }; | |||||
| // 格式化数据来源 | |||||
| export const formatSource = (source?: string) => { | |||||
| if (source === DataSource.Create) { | |||||
| return '用户上传'; | |||||
| } else if (source === DataSource.HandExport) { | |||||
| return '手动导入'; | |||||
| } else if (source === DataSource.AtuoExport) { | |||||
| return '实验自动导入'; | |||||
| } | |||||
| return source; | |||||
| }; | |||||