| @@ -160,10 +160,15 @@ export default [ | |||||
| component: './AutoML/Info/index', | component: './AutoML/Info/index', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '创建自动机器学习', | |||||
| name: '创建实验', | |||||
| path: 'create', | path: 'create', | ||||
| component: './AutoML/Create/index', | component: './AutoML/Create/index', | ||||
| }, | }, | ||||
| { | |||||
| name: '编辑实验', | |||||
| path: 'edit/:id', | |||||
| component: './AutoML/Create/index', | |||||
| }, | |||||
| ], | ], | ||||
| }, | }, | ||||
| ], | ], | ||||
| @@ -71,6 +71,7 @@ export enum DevEditorStatus { | |||||
| Unknown = 'Unknown', // 未启动 | Unknown = 'Unknown', // 未启动 | ||||
| } | } | ||||
| // 服务类型 | |||||
| export enum ServiceType { | export enum ServiceType { | ||||
| Video = 'video', | Video = 'video', | ||||
| Image = 'image', | Image = 'image', | ||||
| @@ -84,3 +85,26 @@ export const serviceTypeOptions = [ | |||||
| { label: '音频', value: ServiceType.Audio }, | { label: '音频', value: ServiceType.Audio }, | ||||
| { label: '文本', value: ServiceType.Text }, | { label: '文本', value: ServiceType.Text }, | ||||
| ]; | ]; | ||||
| // 自动化任务类型 | |||||
| export enum AutoMLTaskType { | |||||
| Classification = 'classification', | |||||
| Regression = 'regression', | |||||
| } | |||||
| // 自动化任务集成策略 | |||||
| export enum AutoMLEnsembleClass { | |||||
| Default = 'default', | |||||
| SingleBest = 'SingleBest', | |||||
| } | |||||
| // 自动化任务重采样策略 | |||||
| export enum AutoMLResamplingStrategy { | |||||
| Holdout = 'holdout', | |||||
| CrossValid = 'crossValid', | |||||
| } | |||||
| export const resamplingStrategyOptions = [ | |||||
| { label: 'holdout', value: AutoMLResamplingStrategy.Holdout }, | |||||
| { label: 'crossValid', value: AutoMLResamplingStrategy.CrossValid }, | |||||
| ]; | |||||
| @@ -22,7 +22,6 @@ function Authorize() { | |||||
| code, | code, | ||||
| }; | }; | ||||
| const [res] = await to(loginByOauth2Req(params)); | const [res] = await to(loginByOauth2Req(params)); | ||||
| debugger; | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const { access_token, expires_in } = res.data; | const { access_token, expires_in } = res.data; | ||||
| setSessionToken(access_token, access_token, expires_in); | setSessionToken(access_token, access_token, expires_in); | ||||
| @@ -4,147 +4,116 @@ | |||||
| * @Description: 创建服务版本 | * @Description: 创建服务版本 | ||||
| */ | */ | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { type ParameterInputObject } from '@/components/ResourceSelect'; | |||||
| import { useComputingResource } from '@/hooks/resource'; | |||||
| import { | |||||
| createServiceVersionReq, | |||||
| getServiceInfoReq, | |||||
| updateServiceVersionReq, | |||||
| } from '@/services/modelDeployment'; | |||||
| import { changePropertyName } from '@/utils'; | |||||
| import { AutoMLTaskType } from '@/enums'; | |||||
| import { addAutoMLReq, getDatasetInfoReq, updateAutoMLReq } from '@/services/autoML'; | |||||
| import { parseJsonText, trimCharacter } from '@/utils'; | |||||
| import { safeInvoke } from '@/utils/functional'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | |||||
| import { useNavigate, useParams } from '@umijs/max'; | import { useNavigate, useParams } from '@umijs/max'; | ||||
| import { App, Button, Form } from 'antd'; | import { App, Button, Form } from 'antd'; | ||||
| import { omit, pick } from 'lodash'; | |||||
| import { useEffect, useState } from 'react'; | |||||
| import { omit } from 'lodash'; | |||||
| import { useEffect } from 'react'; | |||||
| import BasicConfig from '../components/CreateForm/BasicConfig'; | import BasicConfig from '../components/CreateForm/BasicConfig'; | ||||
| import DatasetConfig from '../components/CreateForm/DatasetConfig'; | |||||
| import ExecuteConfig from '../components/CreateForm/ExecuteConfig'; | import ExecuteConfig from '../components/CreateForm/ExecuteConfig'; | ||||
| import SearchConfig from '../components/CreateForm/SearchConfig'; | |||||
| import TrialConfig from '../components/CreateForm/TrialConfig'; | import TrialConfig from '../components/CreateForm/TrialConfig'; | ||||
| import { ServiceData, ServiceOperationType, ServiceVersionData } from '../types'; | |||||
| import { AutoMLData, FormData } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| // 表单数据 | |||||
| export type FormData = { | |||||
| service_name: string; // 服务名称 | |||||
| version: string; // 服务版本 | |||||
| description: string; // 描述 | |||||
| model: ParameterInputObject; // 模型 | |||||
| image: ParameterInputObject; // 镜像 | |||||
| code_config: ParameterInputObject; // 代码 | |||||
| resource: string; // 资源规格 | |||||
| replicas: string; // 副本数量 | |||||
| mount_path: string; // 模型路径 | |||||
| env_variables: { key: string; value: string }[]; // 环境变量 | |||||
| }; | |||||
| function CreateAutoML() { | function CreateAutoML() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const [resourceStandardList, filterResourceStandard] = useComputingResource(); | |||||
| const [operationType, setOperationType] = useState(ServiceOperationType.Create); | |||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const [serviceInfo, setServiceInfo] = useState<ServiceData | undefined>(undefined); | |||||
| const [versionInfo, setVersionInfo] = useState<ServiceVersionData | undefined>(undefined); | |||||
| const params = useParams(); | const params = useParams(); | ||||
| const id = params.id; | |||||
| const id = safeInvoke(Number)(params.id); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const res: | |||||
| | (ServiceVersionData & { | |||||
| operationType: ServiceOperationType; | |||||
| }) | |||||
| | undefined = SessionStorage.getItem(SessionStorage.serviceVersionInfoKey, true); | |||||
| if (res) { | |||||
| setOperationType(res.operationType); | |||||
| setVersionInfo(res); | |||||
| let model, codeConfig, envVariables; | |||||
| if (res.model && typeof res.model === 'object') { | |||||
| model = changePropertyName(res.model, { show_value: 'showValue' }); | |||||
| // 接口返回是数据没有 value 值,但是 form 需要 value | |||||
| model.value = model.showValue; | |||||
| } | |||||
| if (res.code_config && typeof res.code_config === 'object') { | |||||
| codeConfig = changePropertyName(res.code_config, { show_value: 'showValue' }); | |||||
| // 接口返回是数据没有 value 值,但是 form 需要 value | |||||
| codeConfig.value = codeConfig.showValue; | |||||
| } | |||||
| if (res.env_variables && typeof res.env_variables === 'object') { | |||||
| envVariables = Object.entries(res.env_variables).map(([key, value]) => ({ | |||||
| key, | |||||
| value, | |||||
| })); | |||||
| } | |||||
| const formData = { | |||||
| ...omit(res, 'model', 'code_config', 'env_variables'), | |||||
| model: model, | |||||
| code_config: codeConfig, | |||||
| env_variables: envVariables, | |||||
| }; | |||||
| form.setFieldsValue(formData); | |||||
| if (id) { | |||||
| getAutoMLInfo(); | |||||
| } | } | ||||
| return () => { | |||||
| SessionStorage.removeItem(SessionStorage.serviceVersionInfoKey); | |||||
| }; | |||||
| }, []); | |||||
| }, [id]); | |||||
| // 获取服务详情 | // 获取服务详情 | ||||
| const getServiceInfo = async () => { | |||||
| const [res] = await to(getServiceInfoReq(id)); | |||||
| const getAutoMLInfo = async () => { | |||||
| const [res] = await to(getDatasetInfoReq({ id })); | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| setServiceInfo(res.data); | |||||
| form.setFieldsValue({ | |||||
| service_name: res.data.service_name, | |||||
| }); | |||||
| const autoMLInfo: AutoMLData = res.data; | |||||
| const { | |||||
| include_classifier: include_classifier_str, | |||||
| include_feature_preprocessor: include_feature_preprocessor_str, | |||||
| include_regressor: include_regressor_str, | |||||
| exclude_classifier: exclude_classifier_str, | |||||
| exclude_feature_preprocessor: exclude_feature_preprocessor_str, | |||||
| exclude_regressor: exclude_regressor_str, | |||||
| metrics: metrics_str, | |||||
| } = autoMLInfo; | |||||
| const include_classifier = include_classifier_str?.split(',').filter(Boolean); | |||||
| const include_feature_preprocessor = include_feature_preprocessor_str | |||||
| ?.split(',') | |||||
| .filter(Boolean); | |||||
| const include_regressor = include_regressor_str?.split(',').filter(Boolean); | |||||
| const exclude_classifier = exclude_classifier_str?.split(',').filter(Boolean); | |||||
| const exclude_feature_preprocessor = exclude_feature_preprocessor_str | |||||
| ?.split(',') | |||||
| .filter(Boolean); | |||||
| const exclude_regressor = exclude_regressor_str?.split(',').filter(Boolean); | |||||
| const metricsObj = safeInvoke(parseJsonText)(metrics_str) ?? {}; | |||||
| const metrics = Object.entries(metricsObj).map(([key, value]) => ({ | |||||
| name: key, | |||||
| value, | |||||
| })); | |||||
| const formData = { | |||||
| ...autoMLInfo, | |||||
| include_classifier, | |||||
| include_feature_preprocessor, | |||||
| include_regressor, | |||||
| exclude_classifier, | |||||
| exclude_feature_preprocessor, | |||||
| exclude_regressor, | |||||
| metrics, | |||||
| }; | |||||
| form.setFieldsValue(formData); | |||||
| } | } | ||||
| }; | }; | ||||
| // 创建版本 | // 创建版本 | ||||
| const createServiceVersion = async (formData: FormData) => { | |||||
| const envList = formData['env_variables'] ?? []; | |||||
| const image = formData['image']; | |||||
| const model = formData['model']; | |||||
| const codeConfig = formData['code_config']; | |||||
| const envVariables = envList.reduce((acc, cur) => { | |||||
| acc[cur.key] = cur.value; | |||||
| const createExperiment = async (formData: FormData) => { | |||||
| const include_classifier = formData['include_classifier']?.join(','); | |||||
| const include_feature_preprocessor = formData['include_feature_preprocessor']?.join(','); | |||||
| const include_regressor = formData['include_regressor']?.join(','); | |||||
| const exclude_classifier = formData['exclude_classifier']?.join(','); | |||||
| const exclude_feature_preprocessor = formData['exclude_feature_preprocessor']?.join(','); | |||||
| const exclude_regressor = formData['exclude_regressor']?.join(','); | |||||
| const metrics = formData['metrics']?.reduce((acc, cur) => { | |||||
| acc[cur.name] = cur.value; | |||||
| return acc; | return acc; | ||||
| }, {} as Record<string, string>); | |||||
| }, {} as Record<string, number>); | |||||
| const target_columns = trimCharacter(formData['target_columns'], ','); | |||||
| // 根据后台要求,修改表单数据 | // 根据后台要求,修改表单数据 | ||||
| const object = { | const object = { | ||||
| ...omit(formData, ['replicas', 'env_variables', 'image', 'model', 'code_config']), | |||||
| replicas: Number(formData.replicas), | |||||
| env_variables: envVariables, | |||||
| image: image.value, | |||||
| model: changePropertyName( | |||||
| pick(model, ['id', 'name', 'version', 'path', 'identifier', 'owner', 'showValue']), | |||||
| { showValue: 'show_value' }, | |||||
| ), | |||||
| code_config: changePropertyName(pick(codeConfig, ['code_path', 'branch', 'showValue']), { | |||||
| showValue: 'show_value', | |||||
| }), | |||||
| service_id: serviceInfo?.id, | |||||
| ...omit(formData), | |||||
| include_classifier, | |||||
| include_feature_preprocessor, | |||||
| include_regressor, | |||||
| exclude_classifier, | |||||
| exclude_feature_preprocessor, | |||||
| exclude_regressor, | |||||
| metrics: metrics ? JSON.stringify(metrics) : undefined, | |||||
| target_columns, | |||||
| }; | }; | ||||
| const params = | |||||
| operationType === ServiceOperationType.Create | |||||
| ? object | |||||
| : { | |||||
| id: versionInfo?.id, | |||||
| rerun: operationType === ServiceOperationType.Restart ? true : false, | |||||
| deployment_name: versionInfo?.deployment_name, | |||||
| ...object, | |||||
| }; | |||||
| const request = | |||||
| operationType === ServiceOperationType.Create | |||||
| ? createServiceVersionReq | |||||
| : updateServiceVersionReq; | |||||
| const params = id | |||||
| ? { | |||||
| id: id, | |||||
| ...object, | |||||
| } | |||||
| : object; | |||||
| const request = id ? updateAutoMLReq : addAutoMLReq; | |||||
| const [res] = await to(request(params)); | const [res] = await to(request(params)); | ||||
| if (res) { | if (res) { | ||||
| message.success('操作成功'); | message.success('操作成功'); | ||||
| @@ -154,7 +123,7 @@ function CreateAutoML() { | |||||
| // 提交 | // 提交 | ||||
| const handleSubmit = (values: FormData) => { | const handleSubmit = (values: FormData) => { | ||||
| console.log('values', values); | |||||
| createExperiment(values); | |||||
| }; | }; | ||||
| // 取消 | // 取消 | ||||
| @@ -162,15 +131,12 @@ function CreateAutoML() { | |||||
| navigate(-1); | navigate(-1); | ||||
| }; | }; | ||||
| const disabled = operationType !== ServiceOperationType.Create; | |||||
| const disabled = id !== null || id !== undefined; | |||||
| let buttonText = '新建'; | let buttonText = '新建'; | ||||
| let title = '新增服务版本'; | |||||
| if (operationType === ServiceOperationType.Update) { | |||||
| title = '更新服务版本'; | |||||
| let title = '新增实验'; | |||||
| if (id) { | |||||
| title = '更新实验'; | |||||
| buttonText = '更新'; | buttonText = '更新'; | ||||
| } else if (operationType === ServiceOperationType.Restart) { | |||||
| title = '重启服务版本'; | |||||
| buttonText = '重启'; | |||||
| } | } | ||||
| return ( | return ( | ||||
| @@ -180,22 +146,22 @@ function CreateAutoML() { | |||||
| <div> | <div> | ||||
| <Form | <Form | ||||
| name="create-service-version" | name="create-service-version" | ||||
| labelCol={{ flex: '140px' }} | |||||
| labelCol={{ flex: '160px' }} | |||||
| labelAlign="left" | labelAlign="left" | ||||
| form={form} | form={form} | ||||
| onFinish={handleSubmit} | onFinish={handleSubmit} | ||||
| size="large" | size="large" | ||||
| autoComplete="off" | autoComplete="off" | ||||
| initialValues={{ | initialValues={{ | ||||
| execute_type: 'DLC', | |||||
| image_type: 3, | |||||
| advanced_config: [{ key: '', value: '' }], | |||||
| task_type: AutoMLTaskType.Classification, | |||||
| shuffle: false, | |||||
| greater_is_better: true, | |||||
| }} | }} | ||||
| > | > | ||||
| <BasicConfig /> | <BasicConfig /> | ||||
| <ExecuteConfig disabled={disabled} /> | <ExecuteConfig disabled={disabled} /> | ||||
| <TrialConfig /> | <TrialConfig /> | ||||
| <SearchConfig /> | |||||
| <DatasetConfig /> | |||||
| <Form.Item wrapperCol={{ offset: 0, span: 16 }}> | <Form.Item wrapperCol={{ offset: 0, span: 16 }}> | ||||
| <Button type="primary" htmlType="submit"> | <Button type="primary" htmlType="submit"> | ||||
| @@ -1,15 +1,14 @@ | |||||
| /* | /* | ||||
| * @Author: 赵伟 | * @Author: 赵伟 | ||||
| * @Date: 2024-04-16 13:58:08 | * @Date: 2024-04-16 13:58:08 | ||||
| * @Description: 自主机器学习 | |||||
| * @Description: 自主机器学习列表 | |||||
| */ | */ | ||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import { useCacheState } from '@/hooks/pageCacheState'; | import { useCacheState } from '@/hooks/pageCacheState'; | ||||
| import { deleteServiceReq, getServiceListReq } from '@/services/modelDeployment'; | |||||
| import { deleteAutoMLReq, getAutoMLListReq } from '@/services/autoML'; | |||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | |||||
| import tableCellRender, { TableCellValueType } from '@/utils/table'; | import tableCellRender, { TableCellValueType } from '@/utils/table'; | ||||
| import { modalConfirm } from '@/utils/ui'; | import { modalConfirm } from '@/utils/ui'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| @@ -27,7 +26,7 @@ import classNames from 'classnames'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import ExecuteScheduleCell from '../components/ExecuteScheduleCell'; | import ExecuteScheduleCell from '../components/ExecuteScheduleCell'; | ||||
| import RunStatusCell from '../components/RunStatusCell'; | import RunStatusCell from '../components/RunStatusCell'; | ||||
| import { ServiceData, ServiceOperationType } from '../types'; | |||||
| import { AutoMLData } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function AutoMLList() { | function AutoMLList() { | ||||
| @@ -36,7 +35,7 @@ function AutoMLList() { | |||||
| const [cacheState, setCacheState] = useCacheState(); | const [cacheState, setCacheState] = useCacheState(); | ||||
| const [searchText, setSearchText] = useState(cacheState?.searchText); | const [searchText, setSearchText] = useState(cacheState?.searchText); | ||||
| const [inputText, setInputText] = useState(cacheState?.searchText); | const [inputText, setInputText] = useState(cacheState?.searchText); | ||||
| const [tableData, setTableData] = useState<ServiceData[]>([]); | |||||
| const [tableData, setTableData] = useState<AutoMLData[]>([]); | |||||
| const [total, setTotal] = useState(0); | const [total, setTotal] = useState(0); | ||||
| const [pagination, setPagination] = useState<TablePaginationConfig>( | const [pagination, setPagination] = useState<TablePaginationConfig>( | ||||
| cacheState?.pagination ?? { | cacheState?.pagination ?? { | ||||
| @@ -54,9 +53,9 @@ function AutoMLList() { | |||||
| const params: Record<string, any> = { | const params: Record<string, any> = { | ||||
| page: pagination.current! - 1, | page: pagination.current! - 1, | ||||
| size: pagination.pageSize, | size: pagination.pageSize, | ||||
| service_name: searchText, | |||||
| ml_name: searchText, | |||||
| }; | }; | ||||
| const [res] = await to(getServiceListReq(params)); | |||||
| const [res] = await to(getAutoMLListReq(params)); | |||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const { content = [], totalElements = 0 } = res.data; | const { content = [], totalElements = 0 } = res.data; | ||||
| setTableData(content); | setTableData(content); | ||||
| @@ -65,8 +64,8 @@ function AutoMLList() { | |||||
| }; | }; | ||||
| // 删除模型部署 | // 删除模型部署 | ||||
| const deleteService = async (record: ServiceData) => { | |||||
| const [res] = await to(deleteServiceReq(record.id)); | |||||
| const deleteService = async (record: AutoMLData) => { | |||||
| const [res] = await to(deleteAutoMLReq(record.id)); | |||||
| if (res) { | if (res) { | ||||
| message.success('删除成功'); | message.success('删除成功'); | ||||
| // 如果是一页的唯一数据,删除时,请求第一页的数据 | // 如果是一页的唯一数据,删除时,请求第一页的数据 | ||||
| @@ -89,7 +88,7 @@ function AutoMLList() { | |||||
| }; | }; | ||||
| // 处理删除 | // 处理删除 | ||||
| const handleServiceDelete = (record: ServiceData) => { | |||||
| const handleAutoMLDelete = (record: AutoMLData) => { | |||||
| modalConfirm({ | modalConfirm({ | ||||
| title: '删除后,该服务将不可恢复', | title: '删除后,该服务将不可恢复', | ||||
| content: '是否确认删除?', | content: '是否确认删除?', | ||||
| @@ -99,27 +98,22 @@ function AutoMLList() { | |||||
| }); | }); | ||||
| }; | }; | ||||
| // 创建、更新服务 | |||||
| const createService = (type: ServiceOperationType, record?: ServiceData) => { | |||||
| SessionStorage.setItem( | |||||
| SessionStorage.serviceInfoKey, | |||||
| { | |||||
| ...record, | |||||
| operationType: type, | |||||
| }, | |||||
| true, | |||||
| ); | |||||
| // 创建、编辑 | |||||
| const createService = (record?: AutoMLData) => { | |||||
| setCacheState({ | setCacheState({ | ||||
| pagination, | pagination, | ||||
| searchText, | searchText, | ||||
| }); | }); | ||||
| navigate(`/pipeline/autoML/create`); | |||||
| if (record) { | |||||
| navigate(`/pipeline/autoML/edit/${record.id}`); | |||||
| } else { | |||||
| navigate(`/pipeline/autoML/create`); | |||||
| } | |||||
| }; | }; | ||||
| // 查看详情 | // 查看详情 | ||||
| const toDetail = (record: ServiceData) => { | |||||
| const toDetail = (record: AutoMLData) => { | |||||
| setCacheState({ | setCacheState({ | ||||
| pagination, | pagination, | ||||
| searchText, | searchText, | ||||
| @@ -129,7 +123,7 @@ function AutoMLList() { | |||||
| }; | }; | ||||
| // 分页切换 | // 分页切换 | ||||
| const handleTableChange: TableProps<ServiceData>['onChange'] = ( | |||||
| const handleTableChange: TableProps<AutoMLData>['onChange'] = ( | |||||
| pagination, | pagination, | ||||
| _filters, | _filters, | ||||
| _sorter, | _sorter, | ||||
| @@ -140,7 +134,7 @@ function AutoMLList() { | |||||
| } | } | ||||
| }; | }; | ||||
| const columns: TableProps<ServiceData>['columns'] = [ | |||||
| const columns: TableProps<AutoMLData>['columns'] = [ | |||||
| { | { | ||||
| title: '序号', | title: '序号', | ||||
| dataIndex: 'index', | dataIndex: 'index', | ||||
| @@ -153,8 +147,8 @@ function AutoMLList() { | |||||
| }, | }, | ||||
| { | { | ||||
| title: '实验名称', | title: '实验名称', | ||||
| dataIndex: 'service_name', | |||||
| key: 'service_name', | |||||
| dataIndex: 'ml_name', | |||||
| key: 'ml_name', | |||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(false, TableCellValueType.Link, { | render: tableCellRender(false, TableCellValueType.Link, { | ||||
| onClick: toDetail, | onClick: toDetail, | ||||
| @@ -162,23 +156,23 @@ function AutoMLList() { | |||||
| }, | }, | ||||
| { | { | ||||
| title: '实验描述', | title: '实验描述', | ||||
| dataIndex: 'service_type_name', | |||||
| key: 'service_type_name', | |||||
| dataIndex: 'ml_description', | |||||
| key: 'ml_description', | |||||
| width: '20%', | width: '20%', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | ellipsis: { showTitle: false }, | ||||
| }, | }, | ||||
| { | { | ||||
| title: '状态', | title: '状态', | ||||
| dataIndex: 'run_status', | |||||
| key: 'run_status', | |||||
| dataIndex: 'run_state', | |||||
| key: 'run_state', | |||||
| width: '20%', | width: '20%', | ||||
| render: RunStatusCell, | render: RunStatusCell, | ||||
| }, | }, | ||||
| { | { | ||||
| title: '实验实例执行进度', | title: '实验实例执行进度', | ||||
| dataIndex: 'description', | |||||
| key: 'description', | |||||
| dataIndex: 'progress', | |||||
| key: 'progress', | |||||
| render: ExecuteScheduleCell, | render: ExecuteScheduleCell, | ||||
| width: 180, | width: 180, | ||||
| }, | }, | ||||
| @@ -203,15 +197,9 @@ function AutoMLList() { | |||||
| dataIndex: 'operation', | dataIndex: 'operation', | ||||
| width: 400, | width: 400, | ||||
| key: 'operation', | key: 'operation', | ||||
| render: (_: any, record: ServiceData) => ( | |||||
| render: (_: any, record: AutoMLData) => ( | |||||
| <div> | <div> | ||||
| <Button | |||||
| type="link" | |||||
| size="small" | |||||
| key="edit" | |||||
| icon={<KFIcon type="icon-jingxiang" />} | |||||
| onClick={() => createService(ServiceOperationType.Update, record)} | |||||
| > | |||||
| <Button type="link" size="small" key="mirror" icon={<KFIcon type="icon-jingxiang" />}> | |||||
| 镜像 | 镜像 | ||||
| </Button> | </Button> | ||||
| <Button | <Button | ||||
| @@ -219,14 +207,14 @@ function AutoMLList() { | |||||
| size="small" | size="small" | ||||
| key="edit" | key="edit" | ||||
| icon={<KFIcon type="icon-bianji" />} | icon={<KFIcon type="icon-bianji" />} | ||||
| onClick={() => createService(ServiceOperationType.Update, record)} | |||||
| onClick={() => createService(record)} | |||||
| > | > | ||||
| 编辑 | 编辑 | ||||
| </Button> | </Button> | ||||
| <Button | <Button | ||||
| type="link" | type="link" | ||||
| size="small" | size="small" | ||||
| key="run" | |||||
| key="copy" | |||||
| icon={<KFIcon type="icon-fuzhi" />} | icon={<KFIcon type="icon-fuzhi" />} | ||||
| onClick={() => toDetail(record)} | onClick={() => toDetail(record)} | ||||
| > | > | ||||
| @@ -235,7 +223,7 @@ function AutoMLList() { | |||||
| <Button | <Button | ||||
| type="link" | type="link" | ||||
| size="small" | size="small" | ||||
| key="run" | |||||
| key="stop" | |||||
| icon={<KFIcon type="icon-tingzhi" />} | icon={<KFIcon type="icon-tingzhi" />} | ||||
| onClick={() => toDetail(record)} | onClick={() => toDetail(record)} | ||||
| > | > | ||||
| @@ -253,7 +241,7 @@ function AutoMLList() { | |||||
| size="small" | size="small" | ||||
| key="remove" | key="remove" | ||||
| icon={<KFIcon type="icon-shanchu" />} | icon={<KFIcon type="icon-shanchu" />} | ||||
| onClick={() => handleServiceDelete(record)} | |||||
| onClick={() => handleAutoMLDelete(record)} | |||||
| > | > | ||||
| 删除 | 删除 | ||||
| </Button> | </Button> | ||||
| @@ -279,7 +267,7 @@ function AutoMLList() { | |||||
| <Button | <Button | ||||
| style={{ marginLeft: '20px' }} | style={{ marginLeft: '20px' }} | ||||
| type="default" | type="default" | ||||
| onClick={() => createService(ServiceOperationType.Create)} | |||||
| onClick={() => createService()} | |||||
| icon={<KFIcon type="icon-xinjian2" />} | icon={<KFIcon type="icon-xinjian2" />} | ||||
| > | > | ||||
| 新建实验 | 新建实验 | ||||
| @@ -25,7 +25,7 @@ import { type SearchProps } from 'antd/es/input'; | |||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| // import ExecuteScheduleCell from '../components/ExecuteScheduleCell'; | // import ExecuteScheduleCell from '../components/ExecuteScheduleCell'; | ||||
| import { ServiceData, ServiceOperationType } from '@/pages/AutoML/types'; | |||||
| import { OperationType, ServiceData } from '@/pages/AutoML/types'; | |||||
| import RunStatusCell from '../RunStatusCell'; | import RunStatusCell from '../RunStatusCell'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -99,7 +99,7 @@ function AutoMLTable() { | |||||
| }; | }; | ||||
| // 创建、更新服务 | // 创建、更新服务 | ||||
| const createService = (type: ServiceOperationType, record?: ServiceData) => { | |||||
| const createService = (type: OperationType, record?: ServiceData) => { | |||||
| SessionStorage.setItem( | SessionStorage.setItem( | ||||
| SessionStorage.serviceInfoKey, | SessionStorage.serviceInfoKey, | ||||
| { | { | ||||
| @@ -226,7 +226,7 @@ function AutoMLTable() { | |||||
| size="small" | size="small" | ||||
| key="edit" | key="edit" | ||||
| icon={<KFIcon type="icon-rizhi" />} | icon={<KFIcon type="icon-rizhi" />} | ||||
| onClick={() => createService(ServiceOperationType.Update, record)} | |||||
| onClick={() => createService(OperationType.Update, record)} | |||||
| > | > | ||||
| 日志 | 日志 | ||||
| </Button> | </Button> | ||||
| @@ -1,5 +1,5 @@ | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { Col, Form, Input, Row, Select } from 'antd'; | |||||
| import { Col, Form, Input, Row } from 'antd'; | |||||
| function BasicConfig() { | function BasicConfig() { | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -11,43 +11,34 @@ function BasicConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="服务名称" | |||||
| name="service_name" | |||||
| label="实验名称" | |||||
| name="ml_name" | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入服务名称', | |||||
| }, | |||||
| { | |||||
| pattern: /^(?!\d)[\u4e00-\u9fa5\w-]+$/, | |||||
| message: '不能以数字开头,不能存在除了-_以外的特殊字符', | |||||
| message: '请输入实验名称', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Input | |||||
| placeholder="不能以数字开头,不能存在除了-_以外的特殊字符" | |||||
| maxLength={256} | |||||
| showCount | |||||
| allowClear | |||||
| /> | |||||
| <Input placeholder="请输入实验名称" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={20}> | <Col span={20}> | ||||
| <Form.Item | <Form.Item | ||||
| label="描述" | |||||
| name="description" | |||||
| label="实验描述" | |||||
| name="ml_description" | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入描述', | |||||
| message: '请输入实验描述', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Input.TextArea | <Input.TextArea | ||||
| autoSize={{ minRows: 2, maxRows: 6 }} | autoSize={{ minRows: 2, maxRows: 6 }} | ||||
| placeholder="请输入描述" | |||||
| placeholder="请输入实验描述" | |||||
| maxLength={256} | maxLength={256} | ||||
| showCount | showCount | ||||
| allowClear | allowClear | ||||
| @@ -55,7 +46,7 @@ function BasicConfig() { | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| <Row gutter={8}> | |||||
| {/* <Row gutter={8}> | |||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="可见范围" | label="可见范围" | ||||
| @@ -77,7 +68,7 @@ function BasicConfig() { | |||||
| /> | /> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | |||||
| </Row> */} | |||||
| </> | </> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -0,0 +1,59 @@ | |||||
| import ResourceSelect, { | |||||
| ResourceSelectorType, | |||||
| requiredValidator, | |||||
| } from '@/components/ResourceSelect'; | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | |||||
| import { Col, Form, Input, Row } from 'antd'; | |||||
| function DatasetConfig() { | |||||
| return ( | |||||
| <> | |||||
| <SubAreaTitle | |||||
| title="数据集配置" | |||||
| image={require('@/assets/img/search-config-icon.png')} | |||||
| style={{ marginTop: '20px', marginBottom: '24px' }} | |||||
| ></SubAreaTitle> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="数据集" | |||||
| name="dataset" | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择数据集', | |||||
| }, | |||||
| ]} | |||||
| required | |||||
| > | |||||
| <ResourceSelect | |||||
| type={ResourceSelectorType.Dataset} | |||||
| placeholder="请选择数据集" | |||||
| canInput={false} | |||||
| size="large" | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="预测目标列" | |||||
| name="target_columns" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入预测目标列', | |||||
| }, | |||||
| ]} | |||||
| tooltip="数据集 csv 文件中哪几列是预测目标列,逗号分隔" | |||||
| > | |||||
| <Input placeholder="请输入预测目标列" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | |||||
| ); | |||||
| } | |||||
| export default DatasetConfig; | |||||
| @@ -1,19 +1,110 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; | |||||
| import { Button, Col, Flex, Form, Input, Radio, Row } from 'antd'; | |||||
| import ExecuteConfigDLC from './ExecuteConfigDLC'; | |||||
| import ExecuteConfigMC from './ExecuteConfigMC'; | |||||
| import styles from './index.less'; | |||||
| import { | |||||
| AutoMLEnsembleClass, | |||||
| AutoMLResamplingStrategy, | |||||
| AutoMLTaskType, | |||||
| resamplingStrategyOptions, | |||||
| } from '@/enums'; | |||||
| import { Col, Form, Input, InputNumber, Radio, Row, Select, Switch } from 'antd'; | |||||
| type ExecuteConfigProps = { | |||||
| disabled?: boolean; | |||||
| }; | |||||
| // 分类算法 | |||||
| const classificationAlgorithms = [ | |||||
| 'adaboost', | |||||
| 'bernoulli_nb', | |||||
| 'decision_tree', | |||||
| 'extra_trees', | |||||
| 'gaussian_nb', | |||||
| 'gradient_boosting', | |||||
| 'k_nearest_neighbors', | |||||
| 'lda', | |||||
| 'liblinear_svc', | |||||
| 'libsvm_svc', | |||||
| 'mlp', | |||||
| 'multinomial_nb', | |||||
| 'passive_aggressive', | |||||
| 'qda', | |||||
| 'random_forest', | |||||
| 'sgd', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| function ExecuteConfig({ disabled = false }: ExecuteConfigProps) { | |||||
| // 回归算法 | |||||
| const regressorAlgorithms = [ | |||||
| 'adaboost', | |||||
| 'ard_regression', | |||||
| 'decision_tree', | |||||
| 'extra_trees', | |||||
| 'gaussian_process', | |||||
| 'gradient_boosting', | |||||
| 'k_nearest_neighbors', | |||||
| 'liblinear_svr', | |||||
| 'libsvm_svr', | |||||
| 'mlp', | |||||
| 'random_forest', | |||||
| 'sgd', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| // 特征预处理算法 | |||||
| const featureAlgorithms = [ | |||||
| 'densifier', | |||||
| 'extra_trees_preproc_for_classification', | |||||
| 'extra_trees_preproc_for_regression', | |||||
| 'fast_ica', | |||||
| 'feature_agglomeration', | |||||
| 'kernel_pca', | |||||
| 'kitchen_sinks', | |||||
| 'liblinear_svc_preprocessor', | |||||
| 'no_preprocessing', | |||||
| 'nystroem_sampler', | |||||
| 'pca', | |||||
| 'polynomial', | |||||
| 'random_trees_embedding', | |||||
| 'select_percentile_classification', | |||||
| 'select_percentile_regression', | |||||
| 'select_rates_classification', | |||||
| 'select_rates_regression', | |||||
| 'truncatedSVD', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| // 分类指标 | |||||
| export const classificationMetrics = [ | |||||
| 'accuracy', | |||||
| 'balanced_accuracy', | |||||
| 'roc_auc', | |||||
| 'average_precision', | |||||
| 'log_loss', | |||||
| 'precision_macro', | |||||
| 'precision_micro', | |||||
| 'precision_samples', | |||||
| 'precision_weighted', | |||||
| 'recall_macro', | |||||
| 'recall_micro', | |||||
| 'recall_samples', | |||||
| 'recall_weighted', | |||||
| 'f1_macro', | |||||
| 'f1_micro', | |||||
| 'f1_samples', | |||||
| 'f1_weighted', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| // 回归指标 | |||||
| export const regressionMetrics = [ | |||||
| 'mean_absolute_error', | |||||
| 'mean_squared_error', | |||||
| 'root_mean_squared_error', | |||||
| 'mean_squared_log_error', | |||||
| 'median_absolute_error', | |||||
| 'r2', | |||||
| ].map((name) => ({ label: name, value: name })); | |||||
| function ExecuteConfig() { | |||||
| const form = Form.useFormInstance(); | const form = Form.useFormInstance(); | ||||
| const image_type = Form.useWatch('image_type', form); | |||||
| console.log(image_type); | |||||
| const task_type = Form.useWatch('task_type', form); | |||||
| const include_classifier = Form.useWatch('include_classifier', form); | |||||
| const exclude_classifier = Form.useWatch('exclude_classifier', form); | |||||
| const include_regressor = Form.useWatch('include_regressor', form); | |||||
| const exclude_regressor = Form.useWatch('exclude_regressor', form); | |||||
| const include_feature_preprocessor = Form.useWatch('include_feature_preprocessor', form); | |||||
| const exclude_feature_preprocessor = Form.useWatch('exclude_feature_preprocessor', form); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -26,27 +117,349 @@ function ExecuteConfig({ disabled = false }: ExecuteConfigProps) { | |||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="任务类型" | label="任务类型" | ||||
| name="execute_type" | |||||
| name="task_type" | |||||
| rules={[{ required: true, message: '请选择任务类型' }]} | rules={[{ required: true, message: '请选择任务类型' }]} | ||||
| > | > | ||||
| <Radio.Group> | <Radio.Group> | ||||
| <Radio value={'DLC'}>DLC</Radio> | |||||
| <Radio value={'MaxCompute'}>MaxCompute</Radio> | |||||
| <Radio value={AutoMLTaskType.Classification}>分类</Radio> | |||||
| <Radio value={AutoMLTaskType.Regression}>回归</Radio> | |||||
| </Radio.Group> | </Radio.Group> | ||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| <Form.Item dependencies={['execute_type']} noStyle> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="特征预处理算法" | |||||
| name="include_feature_preprocessor" | |||||
| tooltip="如果不选,则使用所有可能的特征预处理算法。否则,将只使用包含的特征预处理算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择特征预处理算法" | |||||
| options={featureAlgorithms} | |||||
| disabled={exclude_feature_preprocessor?.length > 0} | |||||
| mode="multiple" | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="排除特征预处理算法" | |||||
| name="exclude_feature_preprocessor" | |||||
| tooltip="如果不选,则使用所有可能的特征预处理算法。否则,将排除包含的特征预处理算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="排除特征预处理算法" | |||||
| options={featureAlgorithms} | |||||
| disabled={include_feature_preprocessor?.length > 0} | |||||
| mode="multiple" | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Form.Item dependencies={['task_type']} noStyle> | |||||
| {({ getFieldValue }) => { | {({ getFieldValue }) => { | ||||
| return getFieldValue('execute_type') === 'DLC' ? ( | |||||
| <ExecuteConfigDLC disabled={disabled}></ExecuteConfigDLC> | |||||
| return getFieldValue('task_type') === AutoMLTaskType.Classification ? ( | |||||
| <> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="分类算法" | |||||
| name="include_classifier" | |||||
| tooltip="如果不选,则使用所有可能的分类算法。否则,将只使用包含的算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择分类算法" | |||||
| options={classificationAlgorithms} | |||||
| mode="multiple" | |||||
| disabled={exclude_classifier?.length > 0} | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="排除分类算法" | |||||
| name="exclude_classifier" | |||||
| tooltip="如果不选,则使用所有可能的分类算法。否则,将排除包含的算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="排除分类算法" | |||||
| options={classificationAlgorithms} | |||||
| mode="multiple" | |||||
| disabled={include_classifier?.length > 0} | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | |||||
| ) : ( | ) : ( | ||||
| <ExecuteConfigMC disabled={disabled}></ExecuteConfigMC> | |||||
| <> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="回归算法" | |||||
| name="include_regressor" | |||||
| tooltip="如果不选,则使用所有可能的回归算法。否则,将只使用包含的算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择回归算法" | |||||
| options={regressorAlgorithms} | |||||
| mode="multiple" | |||||
| disabled={exclude_regressor?.length > 0} | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="排除的回归算法" | |||||
| name="exclude_regressor" | |||||
| tooltip="如果不选,则使用所有可能的回归算法。否则,将排除包含的算法" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="排除回归算法" | |||||
| options={regressorAlgorithms} | |||||
| mode="multiple" | |||||
| disabled={include_regressor?.length > 0} | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | |||||
| ); | ); | ||||
| }} | }} | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.List name="hyper-parameter"> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="集成方式" | |||||
| name="ensemble_class" | |||||
| tooltip="仅使用单个最佳模型还是集成模型" | |||||
| > | |||||
| <Radio.Group> | |||||
| <Radio value={AutoMLEnsembleClass.Default}>集成模型</Radio> | |||||
| <Radio value={AutoMLEnsembleClass.SingleBest}>单一最佳模型</Radio> | |||||
| </Radio.Group> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Form.Item dependencies={['ensemble_class']} noStyle> | |||||
| {({ getFieldValue }) => { | |||||
| return getFieldValue('ensemble_class') === AutoMLEnsembleClass.Default ? ( | |||||
| <> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="集成模型数量" | |||||
| name="ensemble_size" | |||||
| tooltip="集成模型数量,如果设置为0,则没有集成。默认50" | |||||
| > | |||||
| <InputNumber placeholder="请输入集成模型数量" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="集成最佳模型数量" | |||||
| name="ensemble_nbest" | |||||
| tooltip="仅集成最佳的N个模型" | |||||
| > | |||||
| <InputNumber placeholder="请输入集成最佳模型数量" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </> | |||||
| ) : null; | |||||
| }} | |||||
| </Form.Item> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="最大数量" | |||||
| name="max_models_on_disc" | |||||
| tooltip="定义在磁盘中保存的模型的最大数量。额外的模型数量将被永久删除,它设置了一个集成可以使用多少个模型的上限。必须是大于等于1的整数,默认50" | |||||
| > | |||||
| <InputNumber placeholder="请输入最大数量" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="内存限制(MB)" | |||||
| name="memory_limit" | |||||
| tooltip="机器学习算法的内存限制(MB)。如果auto-sklearn试图分配超过memory_limit MB,它将停止拟合机器学习算法。默认3072" | |||||
| > | |||||
| <InputNumber placeholder="请输入内存限制" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="时间限制(秒)" | |||||
| name="per_run_time_limit" | |||||
| tooltip="单次调用机器学习模型的时间限制(以秒为单位)。如果机器学习算法运行超过时间限制,将终止模型拟合,默认600" | |||||
| > | |||||
| <InputNumber placeholder="请输入时间限制" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="搜索时间限制(秒)" | |||||
| name="time_left_for_this_task" | |||||
| tooltip="搜索合适模型的时间限制(以秒为单位)。通过增加这个值,auto-sklearn有更高的机会找到更好的模型。默认3600。" | |||||
| > | |||||
| <InputNumber placeholder="请输入搜索时间限制" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="重采样策略" | |||||
| name="resampling_strategy" | |||||
| tooltip="重采样策略,分为holdout和crossValid。holdout指定训练数据划分为训练集和验证集的比例。crossValid为交叉验证。" | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择重采样策略" | |||||
| options={resamplingStrategyOptions} | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Form.Item dependencies={['resampling_strategy']} noStyle> | |||||
| {({ getFieldValue }) => { | |||||
| return getFieldValue('resampling_strategy') === AutoMLResamplingStrategy.CrossValid ? ( | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="交叉验证折数" | |||||
| name="folds" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入交叉验证折数', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <InputNumber placeholder="请输入交叉验证折数" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| ) : null; | |||||
| }} | |||||
| </Form.Item> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="shuffle" name="shuffle" tooltip="拆分数据前是否进行 shuffle"> | |||||
| <Switch /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="训练集比率" name="train_size"> | |||||
| <InputNumber placeholder="请输入训练集比率" min={0} max={1} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="测试集比率" | |||||
| name="test_size" | |||||
| tooltip="将数据划分为训练数据和测试数据,测试数据集所占比例" | |||||
| > | |||||
| <InputNumber placeholder="请输入测试集比率" min={0} max={1} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="计算指标" name="scoring_functions" tooltip="需要计算并打印的指标"> | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择计算指标" | |||||
| options={ | |||||
| task_type === AutoMLTaskType.Classification | |||||
| ? classificationMetrics | |||||
| : regressionMetrics | |||||
| } | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="随机种子" name="seed" tooltip="随机种子,将决定输出文件名"> | |||||
| <InputNumber placeholder="请输入随机种子" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="文件夹路径" | |||||
| name="tmp_folder" | |||||
| tooltip="存放配置输出和日志文件的文件夹" | |||||
| rules={[ | |||||
| { | |||||
| pattern: /^\/[a-zA-Z0-9._/-]+$/, | |||||
| message: | |||||
| '请输入正确的文件夹路径,以 / 开头,只支持字母、数字、点、下划线、中横线、斜杠', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Input placeholder="请输入文件夹路径" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| {/* <Form.List name="hyper-parameter"> | |||||
| {(fields, { add, remove }) => ( | {(fields, { add, remove }) => ( | ||||
| <> | <> | ||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| @@ -126,7 +539,7 @@ function ExecuteConfig({ disabled = false }: ExecuteConfigProps) { | |||||
| </div> | </div> | ||||
| </> | </> | ||||
| )} | )} | ||||
| </Form.List> | |||||
| </Form.List> */} | |||||
| </> | </> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -1,5 +1,8 @@ | |||||
| import CodeSelect from '@/components/CodeSelect'; | import CodeSelect from '@/components/CodeSelect'; | ||||
| import ResourceSelect, { ResourceSelectorType } from '@/components/ResourceSelect'; | |||||
| import ResourceSelect, { | |||||
| requiredValidator, | |||||
| ResourceSelectorType, | |||||
| } from '@/components/ResourceSelect'; | |||||
| 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'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -62,12 +65,12 @@ function ExecuteConfigDLC({ disabled = false }: ExecuteConfigDLCProps) { | |||||
| <Form.Item | <Form.Item | ||||
| label="数据集" | label="数据集" | ||||
| name="model" | name="model" | ||||
| // rules={[ | |||||
| // { | |||||
| // validator: requiredValidator, | |||||
| // message: '请选择数据集', | |||||
| // }, | |||||
| // ]} | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择数据集', | |||||
| }, | |||||
| ]} | |||||
| required | required | ||||
| > | > | ||||
| <ResourceSelect | <ResourceSelect | ||||
| @@ -84,12 +87,12 @@ function ExecuteConfigDLC({ disabled = false }: ExecuteConfigDLCProps) { | |||||
| <Form.Item | <Form.Item | ||||
| label="代码配置" | label="代码配置" | ||||
| name="code_config" | name="code_config" | ||||
| // rules={[ | |||||
| // { | |||||
| // validator: requiredValidator, | |||||
| // message: '请选择代码配置', | |||||
| // }, | |||||
| // ]} | |||||
| rules={[ | |||||
| { | |||||
| validator: requiredValidator, | |||||
| message: '请选择代码配置', | |||||
| }, | |||||
| ]} | |||||
| required | required | ||||
| > | > | ||||
| <CodeSelect | <CodeSelect | ||||
| @@ -1,188 +1,119 @@ | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | import SubAreaTitle from '@/components/SubAreaTitle'; | ||||
| import { AutoMLTaskType } from '@/enums'; | |||||
| import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; | import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; | ||||
| import { Button, Col, Flex, Form, Input, Radio, Row, Select } from 'antd'; | |||||
| import { Button, Col, Flex, Form, Input, InputNumber, Radio, Row, Select } from 'antd'; | |||||
| import { classificationMetrics, regressionMetrics } from './ExecuteConfig'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function TrialConfig() { | function TrialConfig() { | ||||
| const form = Form.useFormInstance(); | |||||
| const task_type = Form.useWatch('task_type', form); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <SubAreaTitle | <SubAreaTitle | ||||
| title="Trial配置" | |||||
| title="优化指标" | |||||
| image={require('@/assets/img/trial-config-icon.png')} | image={require('@/assets/img/trial-config-icon.png')} | ||||
| style={{ marginBottom: '26px' }} | style={{ marginBottom: '26px' }} | ||||
| ></SubAreaTitle> | ></SubAreaTitle> | ||||
| <div className={styles['trial-metrics']}> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="优化指标"></Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={24}> | |||||
| <Form.Item | |||||
| label="指标类型" | |||||
| name="version" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请选择指标类型', | |||||
| }, | |||||
| ]} | |||||
| labelCol={{ flex: '120px' }} | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择指标类型" | |||||
| options={[]} | |||||
| fieldNames={{ label: 'name', value: 'name' }} | |||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={24}> | |||||
| <Form.Item | |||||
| label="计算方式" | |||||
| name="version" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请选择计算方式', | |||||
| }, | |||||
| ]} | |||||
| labelCol={{ flex: '120px' }} | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择计算方式" | |||||
| options={[]} | |||||
| fieldNames={{ label: 'name', value: 'name' }} | |||||
| optionFilterProp="name" | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={24}> | |||||
| <Form.Item label="指标权重" tooltip="指标权重" labelCol={{ flex: '120px' }}> | |||||
| <Form.List name="metrics_weight"> | |||||
| {(fields, { add, remove }) => ( | |||||
| <> | |||||
| {fields.map(({ key, name, ...restField }, index) => ( | |||||
| <Flex key={key} align="center" className={styles['advanced-config']}> | |||||
| <Form.Item | |||||
| style={{ flex: 1, marginBottom: 0 }} | |||||
| {...restField} | |||||
| name={[name, 'key']} | |||||
| rules={[{ required: true, message: 'Missing first name' }]} | |||||
| > | |||||
| <Input placeholder="Key" /> | |||||
| </Form.Item> | |||||
| <span style={{ margin: '0 8px' }}>:</span> | |||||
| <Form.Item | |||||
| style={{ flex: 1, marginBottom: 0 }} | |||||
| {...restField} | |||||
| name={[name, 'value']} | |||||
| rules={[{ required: true, message: 'Missing last name' }]} | |||||
| > | |||||
| <Input placeholder="Value" /> | |||||
| </Form.Item> | |||||
| <div style={{ width: '76px', marginLeft: '18px' }}> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="指标名称" name="metric_name"> | |||||
| <Input placeholder="请输入指标名称" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="指标权重" tooltip="用户可自定义优化指标的组合"> | |||||
| <Form.List name="metrics"> | |||||
| {(fields, { add, remove }) => ( | |||||
| <> | |||||
| {fields.map(({ key, name, ...restField }, index) => ( | |||||
| <Flex key={key} align="center" className={styles['advanced-config']}> | |||||
| <Form.Item | |||||
| style={{ flex: 1, marginBottom: 0 }} | |||||
| {...restField} | |||||
| name={[name, 'name']} | |||||
| rules={[{ required: true, message: '请选择指标' }]} | |||||
| > | |||||
| <Select | |||||
| allowClear | |||||
| placeholder="请选择指标" | |||||
| popupMatchSelectWidth={false} | |||||
| options={ | |||||
| task_type === AutoMLTaskType.Classification | |||||
| ? classificationMetrics | |||||
| : regressionMetrics | |||||
| } | |||||
| showSearch | |||||
| /> | |||||
| </Form.Item> | |||||
| <span style={{ margin: '0 8px' }}>:</span> | |||||
| <Form.Item | |||||
| style={{ flex: 1, marginBottom: 0 }} | |||||
| {...restField} | |||||
| name={[name, 'value']} | |||||
| rules={[{ required: true, message: '请输入指标权重' }]} | |||||
| > | |||||
| <InputNumber placeholder="请输入指标权重" min={0} precision={0} /> | |||||
| </Form.Item> | |||||
| <div style={{ width: '76px', marginLeft: '18px' }}> | |||||
| <Button | |||||
| style={{ | |||||
| marginRight: '3px', | |||||
| }} | |||||
| shape="circle" | |||||
| size="middle" | |||||
| // disabled={fields.length === 1} | |||||
| type="text" | |||||
| onClick={() => remove(name)} | |||||
| icon={<MinusCircleOutlined />} | |||||
| ></Button> | |||||
| {index === fields.length - 1 && ( | |||||
| <Button | <Button | ||||
| style={{ | |||||
| marginRight: '3px', | |||||
| }} | |||||
| shape="circle" | shape="circle" | ||||
| size="middle" | size="middle" | ||||
| disabled={fields.length === 1} | |||||
| type="text" | type="text" | ||||
| onClick={() => remove(name)} | |||||
| icon={<MinusCircleOutlined />} | |||||
| onClick={() => add()} | |||||
| icon={<PlusCircleOutlined />} | |||||
| ></Button> | ></Button> | ||||
| {index === fields.length - 1 && ( | |||||
| <Button | |||||
| shape="circle" | |||||
| size="middle" | |||||
| type="text" | |||||
| onClick={() => add()} | |||||
| icon={<PlusCircleOutlined />} | |||||
| ></Button> | |||||
| )} | |||||
| </div> | |||||
| </Flex> | |||||
| ))} | |||||
| {fields.length === 0 && ( | |||||
| <Form.Item style={{ marginBottom: 0 }}> | |||||
| <Button | |||||
| style={{ background: 'white' }} | |||||
| type="dashed" | |||||
| onClick={() => add()} | |||||
| block | |||||
| icon={<PlusCircleOutlined />} | |||||
| > | |||||
| 添加指标权重 | |||||
| </Button> | |||||
| </Form.Item> | |||||
| )} | |||||
| </> | |||||
| )} | |||||
| </Form.List> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={0}> | |||||
| <Col span={24}> | |||||
| <Form.Item | |||||
| label="指标来源" | |||||
| name="service_name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入指标来源', | |||||
| }, | |||||
| ]} | |||||
| tooltip="指标来源" | |||||
| labelCol={{ flex: '120px' }} | |||||
| > | |||||
| <Input placeholder="请输入指标来源" maxLength={256} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={0}> | |||||
| <Col span={24}> | |||||
| <Form.Item | |||||
| label="优化方向" | |||||
| name="execute_type" | |||||
| rules={[{ required: true, message: '请选择优化方向' }]} | |||||
| labelCol={{ flex: '120px' }} | |||||
| > | |||||
| <Radio.Group> | |||||
| <Radio value={1}>越大越好</Radio> | |||||
| <Radio value={2}>越小越好</Radio> | |||||
| </Radio.Group> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| </div> | |||||
| )} | |||||
| </div> | |||||
| </Flex> | |||||
| ))} | |||||
| {fields.length === 0 && ( | |||||
| <Form.Item style={{ marginBottom: 0 }}> | |||||
| <Button | |||||
| style={{ background: 'white' }} | |||||
| type="dashed" | |||||
| onClick={() => add()} | |||||
| block | |||||
| icon={<PlusCircleOutlined />} | |||||
| > | |||||
| 添加指标权重 | |||||
| </Button> | |||||
| </Form.Item> | |||||
| )} | |||||
| </> | |||||
| )} | |||||
| </Form.List> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Row gutter={0}> | |||||
| <Col span={24}> | |||||
| <Form.Item | <Form.Item | ||||
| label="模型名称" | |||||
| name="service_name" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入模型名称', | |||||
| }, | |||||
| ]} | |||||
| tooltip="模型名称" | |||||
| label="优化方向" | |||||
| name="greater_is_better" | |||||
| rules={[{ required: true, message: '请选择优化方向' }]} | |||||
| tooltip="指标组合优化的方向,是越大越好还是越小越好。" | |||||
| > | > | ||||
| <Input placeholder="请输入模型名称" maxLength={256} showCount allowClear /> | |||||
| <Radio.Group> | |||||
| <Radio value={true}>越大越好</Radio> | |||||
| <Radio value={false}>越小越好</Radio> | |||||
| </Radio.Group> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -0,0 +1,80 @@ | |||||
| import { getAccessToken } from '@/access'; | |||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | |||||
| import { getFileListFromEvent } from '@/utils/ui'; | |||||
| import { Button, Col, Form, Input, Row, Upload, type UploadProps } from 'antd'; | |||||
| import { useState } from 'react'; | |||||
| import styles from './index.less'; | |||||
| function UploadConfig() { | |||||
| const [uuid] = useState(Date.now()); | |||||
| // 上传组件参数 | |||||
| const uploadProps: UploadProps = { | |||||
| action: '/api/mmp/autoML/upload', | |||||
| headers: { | |||||
| Authorization: getAccessToken() || '', | |||||
| }, | |||||
| defaultFileList: [], | |||||
| }; | |||||
| return ( | |||||
| <> | |||||
| <SubAreaTitle | |||||
| title="数据集配置" | |||||
| image={require('@/assets/img/search-config-icon.png')} | |||||
| style={{ marginTop: '20px', marginBottom: '24px' }} | |||||
| ></SubAreaTitle> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item label="数据集名称" name="dataset_name"> | |||||
| <Input placeholder="请输入数据集名称" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Row gutter={8}> | |||||
| <Col span={10}> | |||||
| <Form.Item | |||||
| label="预测目标列" | |||||
| name="target_columns" | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请输入预测目标列', | |||||
| }, | |||||
| ]} | |||||
| tooltip="数据集 csv 文件中哪几列是预测目标列,逗号分隔" | |||||
| > | |||||
| <Input placeholder="请输入预测目标列" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | |||||
| </Col> | |||||
| </Row> | |||||
| <Form.Item | |||||
| label="数据集文件" | |||||
| name="fileList" | |||||
| valuePropName="fileList" | |||||
| getValueFromEvent={getFileListFromEvent} | |||||
| labelCol={{ span: 24 }} | |||||
| wrapperCol={{ span: 24 }} | |||||
| rules={[ | |||||
| { | |||||
| required: true, | |||||
| message: '请上传数据集文件', | |||||
| }, | |||||
| ]} | |||||
| > | |||||
| <Upload {...uploadProps} data={{ uuid: uuid }} accept=".csv"> | |||||
| <Button | |||||
| className={styles['upload-button']} | |||||
| type="default" | |||||
| icon={<KFIcon type="icon-shangchuan" />} | |||||
| > | |||||
| 上传文件 | |||||
| </Button> | |||||
| <div className={styles['upload-tip']}>只允许上传 .csv 格式文件</div> | |||||
| </Upload> | |||||
| </Form.Item> | |||||
| </> | |||||
| ); | |||||
| } | |||||
| export default UploadConfig; | |||||
| @@ -128,3 +128,14 @@ | |||||
| border: 1px dashed #e0e0e0; | border: 1px dashed #e0e0e0; | ||||
| border-radius: 8px; | border-radius: 8px; | ||||
| } | } | ||||
| .upload-tip { | |||||
| margin-top: 5px; | |||||
| color: @text-color-secondary; | |||||
| font-size: 14px; | |||||
| } | |||||
| .upload-button { | |||||
| height: 46px; | |||||
| font-size: 15px; | |||||
| } | |||||
| @@ -1,6 +1,54 @@ | |||||
| import { type ParameterInputObject } from '@/components/ResourceSelect'; | |||||
| // 操作类型 | // 操作类型 | ||||
| export enum ServiceOperationType { | |||||
| export enum OperationType { | |||||
| Create = 'Create', // 创建 | Create = 'Create', // 创建 | ||||
| Update = 'Update', // 更新 | Update = 'Update', // 更新 | ||||
| Restart = 'Restart', // 重启 | |||||
| } | } | ||||
| // 表单数据 | |||||
| export type FormData = { | |||||
| ml_name: string; // 实验名称 | |||||
| ml_description: string; // 实验描述 | |||||
| ensemble_class?: string; // 集成构建 | |||||
| ensemble_nbest?: string; | |||||
| ensemble_size?: number; | |||||
| include_classifier?: string[]; | |||||
| include_feature_preprocessor?: string[]; | |||||
| include_regressor?: string[]; | |||||
| exclude_classifier?: string[]; | |||||
| exclude_feature_preprocessor?: string[]; | |||||
| exclude_regressor?: string[]; | |||||
| max_models_on_disc?: number; | |||||
| memory_limit?: number; | |||||
| metric_name?: string; | |||||
| greater_is_better: boolean; | |||||
| per_run_time_limit?: number; | |||||
| resampling_strategy?: string; | |||||
| scoring_functions?: string; | |||||
| shuffle?: boolean; | |||||
| seed?: number; | |||||
| target_columns: string; | |||||
| task_type: string; | |||||
| test_size?: number; | |||||
| train_size?: number; | |||||
| time_left_for_this_task: number; | |||||
| tmp_folder?: string; | |||||
| metrics?: { name: string; value: number }[]; | |||||
| dataset: ParameterInputObject; // 模型 | |||||
| }; | |||||
| export type AutoMLData = { | |||||
| id: string; | |||||
| progress: number; | |||||
| run_state: string; | |||||
| state: number; | |||||
| metrics?: string; | |||||
| include_classifier?: string; | |||||
| include_feature_preprocessor?: string; | |||||
| include_regressor?: string; | |||||
| exclude_classifier?: string; | |||||
| exclude_feature_preprocessor?: string; | |||||
| exclude_regressor?: string; | |||||
| dataset?: string; | |||||
| }; | |||||
| @@ -0,0 +1,55 @@ | |||||
| /* | |||||
| * @Author: 赵伟 | |||||
| * @Date: 2024-11-18 10:18:27 | |||||
| * @Description: 自动机器学习请求 | |||||
| */ | |||||
| import { request } from '@umijs/max'; | |||||
| // 分页查询自动学习 | |||||
| export function getAutoMLListReq(params) { | |||||
| return request(`/api/mmp/autoML`, { | |||||
| method: 'GET', | |||||
| params, | |||||
| }); | |||||
| } | |||||
| // 查询自动学习详情 | |||||
| export function getDatasetInfoReq(params) { | |||||
| return request(`/api/mmp/autoML/getAutoMlDetail`, { | |||||
| method: 'GET', | |||||
| params, | |||||
| }); | |||||
| } | |||||
| // 新增自动学习 | |||||
| export function addAutoMLReq(data) { | |||||
| return request(`/api/mmp/autoML`, { | |||||
| method: 'POST', | |||||
| data, | |||||
| }); | |||||
| } | |||||
| // 编辑自动学习 | |||||
| export function updateAutoMLReq(data) { | |||||
| return request(`/api/mmp/autoML`, { | |||||
| method: 'PUT', | |||||
| data, | |||||
| }); | |||||
| } | |||||
| // 删除自动学习 | |||||
| export function deleteAutoMLReq(id) { | |||||
| return request(`/api/mmp/autoML/${id}`, { | |||||
| method: 'DELETE', | |||||
| }); | |||||
| } | |||||
| // 运行自动学习 | |||||
| export function runAutoMLReq(id) { | |||||
| return request(`/api/mmp/autoML/${id}`, { | |||||
| method: 'POST', | |||||
| params, | |||||
| }); | |||||
| } | |||||
| @@ -4,6 +4,16 @@ | |||||
| * @Description: 函数式编程 | * @Description: 函数式编程 | ||||
| */ | */ | ||||
| /** | |||||
| * Safely invokes a function with a given value, returning the result of the | |||||
| * function or the provided value if it is `undefined` or `null`. | |||||
| * | |||||
| * @template T - The type of the input value. | |||||
| * @template M - The type of the output value. | |||||
| * @param {function} fn - The function to be invoked with the input value. | |||||
| * @returns {function} A function that takes a value, invokes `fn` with it if | |||||
| * it's not `undefined` or `null`, and returns the result or the original value. | |||||
| */ | |||||
| export function safeInvoke<T, M>( | export function safeInvoke<T, M>( | ||||
| fn: (value: T) => M | undefined | null, | fn: (value: T) => M | undefined | null, | ||||
| ): (value: T | undefined | null) => M | undefined | null { | ): (value: T | undefined | null) => M | undefined | null { | ||||
| @@ -241,3 +241,18 @@ export const tableSorter = (a: any, b: any) => { | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| }; | }; | ||||
| /** | |||||
| * Trim the given character from both ends of the given string. | |||||
| * | |||||
| * @param {string} ch - the character to trim | |||||
| * @param {string} str - the string to trim | |||||
| * @return {string} the trimmed string | |||||
| */ | |||||
| export const trimCharacter = (str: string, ch: string): string => { | |||||
| if (str === null || str === undefined) { | |||||
| return str; | |||||
| } | |||||
| const reg = new RegExp(`^${ch}|${ch}$`, 'g'); | |||||
| return str.trim().replace(reg, ''); | |||||
| }; | |||||